640 x 480 image formation from OV5647 raspberry pi camera v1 - opencv

I want to figure out exactly what is happening when I create a 640x480 pixel image from the OV5647 Pi camera v1.
This is what I think so far:
We start with the full FoV 2592x1944 pixel resolution with aspect ratio 4:3.
Now 640x480 resolution image is also 4:3 aspect and based on full FoV.
We start by binning:
| Width | Height |
|----|----|
|2592|1944|
|1296|972|
|648|486|
e.g. 2592/2 = 1296; 1296/2 = 648
1944/2 = 972; 972/2=486
So after binning we get resolution of 648 x 486 but we want the output to be 640 x 480 so we have to deal with the extra 8 pixels horizontally and the extra 6 vertical pixels on the binned image.
My question is what actually happens to create an output image frame for the following cases:
640 x 480 resolution video is recorded with raspivid e.g. console command:
raspivid -o myvid.h264 -w 640 -h 480 -t 60000
If possible could someone explain the slight variation I see with 640 x 480 images create with raspivid and with OpenCV 4.0.0. The content of the images seems somewhat different e.g. slightly displaced but I am not sure if this is simple displacement e.g. taking from slightly different FoV or is one of the outputs actually performing a scale operation on the 648x486 binned image to generate the 640x480 result e.g. I have assumed that only binning and FoV clipping is done but actual scaling is possibility too especially for opencv.
Code for camera image is captured with OpenCV 4.0.0:
cv::VideoCapture* video_capture_cap_;
video_capture_cap_ = new cv::VideoCapture();
video_capture_cap_->open(0);
if (video_capture_cap_->isOpened()) {
video_capture_cap_->set(
cv::CAP_PROP_FRAME_WIDTH,
640);
video_capture_cap_->set(
cv::CAP_PROP_FRAME_HEIGHT,
480);
video_capture_cap_->set(
cv::CAP_PROP_FPS,
49);

It would seem the answer is the following:
raspivid -o myvid.h264 -w 640 -h 480 -t 60000
produces a video file of the .h264 format.
Frames of the video are produced by 4x4 binning followed by scale.
As output is 640 x 480 frames, the following is done.
2592/2 = 1296; 1296/2 = 648
1944/2 = 972; 972/2=486
then scale 648 x 486 to 640 x 480 using a scale factor of (640.0/648.0).
I am not sure if this concurs with the raspivid documentation which seems to suggest the contrary e.g. from documentation I was expecting cropping to the correct image size not scaling. However, inspecting video output suggests the that scaling takes place rather than cropping.
Method was to take video as above of camera calibration checkerboard. Extract frames from video and compare size of and position checkerbaord squares with corresponding image taken via cv::VideoCapture.
Image from cv::VideoCapture was formulated as described by Christoph Rackwitz e.g.
do binning as above to get 648 x 486 image then crop to the desired 640 x 480 image size. Cropping appears to take the central 640 x 480 image regione.g. it drops the first 3 rows and the last 3 rows of the 648 x 486 image and drops the first and last 4 columns in each row.

Related

What happen if I set a smaller resolution in to a camera which has a constant resolution?

I have a USB camera and I know that it has a constant resolution 1920x1080.
When I use opencv's VideoCapture to set resolution to 1080x720 using following way
video_capture.set(cv2.CAP_PROP_FRAME_WIDTH, 1080)
video_capture.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
What is happening essentially?
It subsample from the camera buffer directly or read the whole image and resize to 1080x720?
If opencv subsample from the camera buffer directly, then apply these setting would increase the reading speed right?
If opencv read the whole image and resize to 1080x720, then apply these setting would decrease the reading spped right?
What kind of situation should it belong to?
I tried setting the resolution to different values
import cv2
cap = cv2.VideoCapture(0)
w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
for i in range(1, 2000):
cap.set(cv2.CAP_PROP_FRAME_WIDTH, int(i))
if w != cap.get(cv2.CAP_PROP_FRAME_WIDTH):
h = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
w = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
print(str(int(w)), str(int(h)))
cap.release()
cv2.destroyAllWindows()
This is the result I get
160 120
320 240
640 480
848 480
960 540
1280 720
Since I don't have 1920x1080 option, it can be concluded that cap.set property can be used only if the camera supports the desired resolution.
Note that resizing operation is well implemented in OpenCV. So, even for the lowest power computers, such as Raspberry Pi, the time passes for resizing is ignorable compared to other imaging operations. (Unlike Gaussian blur, for instance, whose computational time is also ignorable in normal computers, but the operation takes a lot of time in RPi.)

How to calculate PSNR of images of different sizes resulted from an image reconstruction process

Say if I have an image size of 250 x 250 and I've downscaled it by a factor of 3 using PIL library like this:
from PIL import Image
width, height = original_img.size
downscaled_img = original_img.resize((width // 3, height // 3), Image.BICUBIC)
print(downscaled_img.size) // should be 83 x 83 or something like that
So, now if I want to scale it back by a factor 3 I'd get an image size of 249 x 249, which is different from its orginal copy. In this case, I wonder how can I calculate the PSNR between these two images? Should I remove 1 pixel from all borders from the original image to make it 249 x 249 and then calculate PSNR?
Thanks a lot,
JZ

How to set resolution of image

I am using OpenCV to generate images with depth of 1 bit to cut in a laser cutter (Github repo here). I save them with:
cv2.imwrite(filepath, img, [cv2.IMWRITE_PNG_BILEVEL, 1])
Each pixel corresponds to 0.05mm (called "scan gap" in the laser cutter). A sample image has 300 x 306 pixels and appears in the laser cutter software (LaserCut Pro 5) with size 30 mm x 30 mm. This corresponds to a resolution of 254 pixels per inch and the uncommon value could be from the software. I want a size of 15 mm x 15.3 mm and want to set a higher resolution to achieve that. I could resize by hand, but if I make a mistake, the pixels are no longer exactly aligned with the scan gap of the laser, resulting in inaccuracies in the engraving.
Does OpenCV have a way to set the resolution or final size of the image?

How does Pixels Per Centimeter relate to zoom and pixelation of an image

I'm working on something where an admin puts in a threshold for PPI of an image, for example 35. If the uploaded image has PPI of greater than 35 then return true or else return false.
So I'm finding out the PPI of an image using imageMagick:
identify -format "%x x %y" myimg.png
This gives me numbers, for example, 5.51 PixelsPerCentimeter and I convert them to PixelsPerInch by 5.51 * 2.35
This all works fine. However, I am curious as to how the PPI relates to the zoom factor of an image.
Questions
Does a low resolution (say, 10 PPI) image mean it can't be zoomed in as much as a high resolution image can (say, 72 PPI)?
Well I'm sure a low resolution can be zoomed in at a high percentage but the image quality won't be as good i.e. it will be pixelated?
Is there a better metric that I should be looking at rather than PPI to determine whether an image is high resolution or low resolution.

Pixels of an image

I have a stupid question:
I have a black circle on white background, something like:
I have a code in Matlab that gets an image with a black circle and returns the number of pixels in the circle.
will I get the same number of pixels in a camera of 5 mega pixel and a camera of 8 mega pixel?
The short answer is: Under most circumstances, No. 8MP should have more pixels than 5MP, However...
That depends on many factors related to the camera and the images that you take:
Focal length of the cameras, and other optics parameters. Consider a fish-eye lens to understand my point.
Distance of the circle from the camera. Obviously, closer objects appear larger.
What the camera does with the pixels from the sensor. For example, 5MP cameras that works in a down-scaled regime, outputting 3MP instead.
its depends on the Resolution is how many pixels you have counted horizontally or vertically when used to describe a stored image.
Higher mega pixel cameras offer the ability to print larger images.
For example a 6mp camera offers a resolution of 3000 x 2000 pixels. If you allow 300dpi (dots per inch) for print quality, this would give you a print of approx 10 in x 7 in. 3000 divided by 300 = 10, 2000 divided by 300 = approx 7
A 3.1mp camera offers a resolution of 2048 x 1536 pixels which gives a print size of 7in x 5in

Resources