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?
Related
I have the following rather simple problem and unfortunately I am not getting forward.
Imagine a simple 2D image with pixels and a unique value for each pixel of the image.
For example, let the image be 512x512 pixels in size and 10 nm x 10 nm in dimension. Since I want to view the image in frequency space, I calculate the Fourier transform of the image.
Of course, the image still has 512x512 pixels, but what about the units? I would say the physical units are now 1/m, but what happens to the 10 nm?
So what would be the dimensions of my image after the Fourier transform? Would be very grateful for any help.
The first frequency bin (after the DC bin) stands for "1 cycle" across the whole domain, so that means 1 / (10 nm) in your case, i.e. wavelength is 10 nm. The pattern continues, next bin stands for 2 cycles, or 2 / (10 nm), i.e. wavelength is 5 nm.
I'm not sure it makes sense to translate the length units in this process.
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.
somehow detecting charuco diamonds does not work with bigger images for me. With my original images of 1920x1080 it neither recognizes the ids reliably (the diamond ids elements are switching places every time). In the first image, you can see it recognizes (7, 9, 45, 2).
Then I tried downsampling the images to 960x540, and dividing the calibration params, f, c, to half, and it works! The id is correctly recognized as (2,7,45,9) and the pose estimation is accurate.
How to make it work for bigger images? I tried changing the detection parameters depending on absolute pixel units (not relative to image size). Here is a list of my current parameters. I realized increasing the Window size for threasholding helps recognizing the squares, but not for id or pose estimation.
nmarkers: 1024
adaptiveThreshWinSizeMin: 13
adaptiveThreshWinSizeMax: 113
adaptiveThreshWinSizeStep: 10
adaptiveThreshWinSize: 42
adaptiveThreshConstant: 7
minMarkerPerimeterRate: 0.1
maxMarkerPerimeterRate: 4.0
polygonalApproxAccuracyRate: 0.05
minCornerDistance: 10.0
minDistanceToBorder: 10
minMarkerDistance: 10.0
minMarkerDistanceRate: 0.05
doCornerRefinement: false
cornerRefinementWinSize: 5
cornerRefinementMaxIterations: 30
cornerRefinementMinAccuracy: 0.1
markerBorderBits: 1
perspectiveRemovePixelPerCell: 8
perspectiveRemoveIgnoredMarginPerCell: 0.13
maxErroneousBitsInBorderRate: 0.04
minOtsuStdDev: 5.0
errorCorrectionRate: 0.6
Any hints?
thank you!
At the end I needed to patch the opencv aruco module. It was a matter of a certain treshold escalating too fast (to the 4th) to the image size (closestCandidateDistance in refineDetectedMarkers). The solution was to make minRepDistance in detectCharucoDiamond to only scale linearly with the image size.
Full answer and patch in the opencv forum.
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.
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