OpenCV corrupting HQ Rapsicam data above 4000×3040 resoution?

Question:

The Problem

When I take an image using OpenCV that is larger than 4000 pixels wide, using a high quality picam, the image data appears corrupted (it’s offset).

More Detail

As stated, I cannot get a good image when using OpenCV at over 4000 pixels wide of resolution. I know that the hardware is not the issue as I can get a clean full resolution (4056×3040) image when I use the raspistill command:

sudo raspistill -o testing.tiff -w 4056 -h 3040

Here is the clean output from raspistill:

4056×3040 image – Clean Image produced by raspistill command

I am able to capture images using OpenCV in either Python:

import cv2 as cv

def main():
    cap = cv.VideoCapture("/dev/video2", cv.CAP_V4L2)
    cap.set(cv.CAP_PROP_FRAME_WIDTH, 4056)#works fine up to 4000
    cap.set(cv.CAP_PROP_FRAME_HEIGHT, 3040)

    if not(cap.isOpened()):
        print("could not open video device")
    else:
        print("cap opened")

    ret, frame = cap.read()
    if(ret):
        cv.imwrite("./test_im.jpg", frame)
        print("image saved")
    else:
        print("no capture data returned")
    

if __name__ == "__main__":
    main() 

Or I can capture in OpenCV with C++:

#include <opencv2/opencv.hpp>
#include <iostream>

int main(int argc, char *argv[]){
    cv::Mat frame;
    cv::VideoCapture cap("/dev/video2", cv::CAP_V4L2);

    cap.set(cv::CAP_PROP_FRAME_WIDTH, 4056);
    cap.set(cv::CAP_PROP_FRAME_HEIGHT, 3040);


    if(cap.isOpened() == false){
        std::cout << "cap not opened" << std::endl;
    }
    else{
        std::cout << "cap opened" << std::endl;
    }
    cap >> frame;

    if(frame.empty()){
        std::cout << "empy frame";
    }
    else{
        std::cout << "successfully captured image" << std::endl;
        cv::imwrite("test.tiff", frame);
    }
}

The Result is the same either way.

Here is the corrupted output from OpenCV:

4056×3040 image – Corrupted and captured by OpenCV

To me it seems as if it something was going wrong with the timing of the capture. The format of which I save it to does not make a difference either. I have tried .png, .jpg, and .tiff. The result is always the same. After reboot the results remain the same.

If I reduce the desired capture resolution to only 4000×3040 then I am able to successfully make a capture. Here are the results:

4000×3040 image – successfully captured by OpenCV

I am not sure why this is happening. And would really appreciate any help! Let me know if there is any other information that could be useful!

System

  • Raspberry Pi 4B with 4GB RAM.
  • High Quality Picam
  • Running Ubuntu 20.04
  • OpenCV 4.5.5
Asked By: Slacker

||

Answers:

I determined that the issue was related to a necessary buffer required by the Raspberry Pi and OpenCV. I believe it is related to this answer on stack overflow.

As a result, I was able to fix the image streaking by reducing the resolution that I was requesting to be a multiple of 32 in both length and width e.g. 4032×3040 (instead of 4056×3040). This allowed me to get almost full resolution images, and was sufficient for the task. I was unable to figure out how I would be able to get a full resolution image using OpenCV and a High Quality Raspicam.

Answered By: Slacker