How to get cropped image after fisheye calibration in OpenCV - opencv

I am trying to calibrated fisheye camera in OpenCV 3.2. This is a code:
Mat newCamMat;
cameraMatrix= getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 0, imageSize, 0); //Does not change anything
fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix, distCoeffs, imageSize,
Matx33d::eye(), newCamMat, 1);
fisheye::initUndistortRectifyMap(cameraMatrix, distCoeffs, Matx33d::eye(), newCamMat, imageSize,
CV_16SC2, map1, map2);
I used these flags in calibration:
fisheye::CALIB_FIX_SKEW | fisheye::CALIB_RECOMPUTE_EXTRINSIC | fisheye::CALIB_CHECK_COND
I want to get image cropped without the black areas around the usable area. For non-fisheye calibration I did it by setting alpha. For fisheye I dont know how to change it.Any suggestions?
Desired result (inside the red rectangle)
Calibration result

You can use a masked setTo to set the Alpha channel value to be transparent.
Mat img = imread("fisheye.png",-1), gray, mask;
cvtColor(img, gray, cv::COLOR_BGR2GRAY);
threshold(gray, mask, 0, 255, cv::THRESH_BINARY_INV);
cvtColor(img, img, cv::COLOR_BGR2BGRA);
img.setTo(Scalar(0,0,0,0),mask);

Related

openCV inRange masking

I'm using Opencv 3.0 to get only the colored objects in an image. Therefore i create and use a mask.
#include <opencv2\opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
namedWindow("Display", CV_WINDOW_AUTOSIZE);
namedWindow("Orignial", CV_WINDOW_AUTOSIZE);
namedWindow("Mask", CV_WINDOW_AUTOSIZE);
// First load your image
Mat mSrc = imread("IMG_0005_AUSZUG2.png", CV_LOAD_IMAGE_COLOR);
Mat mGray = Mat::zeros(mSrc.size(), mSrc.type());
cvtColor(mSrc, mGray, CV_BGR2GRAY);
// define your mask
Mat mask = Mat::zeros(mSrc.size(), mSrc.type());
// define destination image
Mat dstImg = Mat::zeros(mSrc.size(), mSrc.type());
//finding mask
inRange(mSrc, Scalar(90, 90, 90), Scalar(180, 180, 180), mask);
// combination of mask and Source image
dilate(mask, mask, Mat(), Point(-1, -1));
bitwise_not(mask, mask);
//cvtColor(mask, mask, CV_GRAY2BGR);
mSrc.copyTo(dstImg, mask);
//bitwise_and(mSrc, mSrc, dstImg, mask);
imshow("Mask", mask);
imshow("Orignial", mSrc);
imshow("Display", dstImg);
waitKey(0);
return 0;
}
As you can see the result image is not the intended one. Only the colored objects should stay, because they have a white background in the mask, but it seems that the result image is a combination of source and mask.
Anybody know how to fix this ?
Source:
Mask:
Result:
To understand your requirement- you have an image with some coloured objects in it, in a white background, and you essentially want an result image containing the same coloured objects in a black background instead.
If that's the case, inRange will not help because you've essentially kept the threshold between grey values 90 and 180, so your code will discard dark objects as well.
To ensure that you obtain a mask that is black only in the white background regions, I would suggest using the threshold function instead, as shown:
//finding mask
//inRange(mSrc, Scalar(90, 90, 90), Scalar(180, 180, 180), mask);
threshold(mGray, mask, 220, 255, THRESH_BINARY_INV);
This function will ensure that any pixel value in your greyscale image above 220 will be set to 0 in the binary mask.
To superimpose the binary mask over the source image, you should use the subtract method, as shown:
cvtColor(mask,mask,CV_GRAY2BGR);//change thresh to a 3 channel image
Mat mResult = Mat::zeros(mSrc.size(), mSrc.type());
subtract(mask,mSrc,mResult);
subtract(mask,mResult,mResult);

thresholding an image with bright zones

I am developing an app for iOS with openCV that take a picture from a monitor and extract a curve, but when the image has some bright zones after thresholding, I don't get the complete curve but some black zones
Original image
processed image after thresholding
original = [MAOpenCV cvMatGrayFromUIImage:_sourceImage];
cv::threshold(original, original, 70, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);
findContours(original, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );
cv::Mat skel(original.size(), CV_8UC1, cv::Scalar(0));
int idx = 0;
for(; idx >= 0; idx = hierarchy[idx][0])
{
if (contours[idx].size()>250 && idx>-1){
cv::Scalar color( 255,255,255);
drawContours(skel, contours, idx, color, CV_FILLED, 8, hierarchy);
}
}
cv::threshold(skel, skel, 100, 255, CV_THRESH_BINARY_INV);
cv::erode(skel,skel,cv::Mat(),cv::Point(-1,-1),2);
So how I can process the image to extract the curve when the image have some bright zones like the example
When you have a background with an uneven illumination, you may want to apply first a White Top-Hat (or here for MatLab, and here for OpenCV).
Here is the result I got using a structuring element of type disk with radius 3.
Then, whatever thresholding method you choose will work.
Wouldn't be sufficient to use Otsu's thresholding?
Code fragment:
import cv2
image = cv2.imread('d:/so.jpg', cv2.IMREAD_GRAYSCALE)
threshold, thresholded = cv2.threshold(image, 0, 255, type=cv2.THRESH_BINARY + cv2.THRESH_OTSU)
print(threshold)
cv2.imshow('so', image);
cv2.imshow('thresholded', thresholded)
cv2.waitKey(0)

OpenCV Image processing

I have an Image that I would like to zoom into and view at high detail. It is of unknown size and mostly black and white with some text on it. When I zoom in the text becomes unreadable and I thought it was to do with not having enough pixels/texels to display so I upscaled the image by a factor of 2. Now that I have scaled it, it is still unreadable.
Then I started to use OpenCV with :
void resizeFirst(){
Mat src = imread( "../floor.png", 1 );
Mat tmp;
resize(src,tmp,Size(),3,3,INTER_CUBIC);
Mat dst = tmp.clone();
Size s(3,3);
//blur( tmp, dst, s, Point(-1,-1) );//homogeneous
GaussianBlur(tmp, dst, s, 3);//gaussian
//medianBlur ( tmp, dst, 5 );//median
//bilateralFilter ( tmp, dst, 5, 5*2, 5/2 );
addWeighted(tmp, 1.5, dst, -0.5, 0, dst);
imwrite("sharpenedImage.png",dst);
}
void blurFirst(){
Mat src = imread( "../floor.png", 1 );
Size s(3,3);
Mat dst;
GaussianBlur(src, dst, s, 3);//gaussian
addWeighted(src, 2, dst, -1, 0, dst);
Mat tmp;
resize(dst,tmp,Size(),3,3,INTER_CUBIC);
imwrite("sharpenedImage0.png",tmp);
}
and the output is better but the image still isnt sharp. Does anyone have any ideas on how to keep text sharp when zooming into an image?
EDIT: below are sample images.
The first one is the smaller res original and the second I resized and tried to do gaussian sharpening as per below
Resize function offers different interpolation methods
INTER_NEAREST nearest-neighbor interpolation
INTER_LINEAR bilinear interpolation (used by default)
INTER_AREA resampling using pixel area relation. It may be the preferred method for image decimation, as it gives moire-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method
INTER_CUBIC bicubic interpolation over 4x4 pixel neighborhood
INTER_LANCZOS4 Lanczos interpolation over 8x8 pixel neighborhood
try all the interpolation methods and use the one that suits you the most. The resize function will however change the aspect ratio of your image.

Perform Canny Edge in HSV Image

I had converted an BGR image to HSV to detect the black circles, then how I perform Canny edge on the HSV image? I had tried but it doesn't works at all.
IplImage *capturedImg = cvLoadImage("template.jpg",1);
IplImage* imgHSV = cvCreateImage(cvGetSize(capturedImg), 8, 3);
cvCvtColor(capturedImg, imgHSV, CV_BGR2HSV);
IplImage* imgThreshed = cvCreateImage(cvGetSize(capturedImg), 8, 1);
cvInRangeS(imgHSV, cvScalar(0, 0,0), cvScalar(255, 255, 38),imgThreshed);
cvShowImage("HSV",imgThreshed);
IplImage*cannyImg2=cvCreateImage(cvGetSize(imgThreshed),8,1);
cvCanny(grayscaleImg2,cannyImg2,0,255,3);
cvShowImage("canny2",cannyImg2);
The first image is eyes detection, then I use HSV image to detect the pupil, so how can I know the position of pupils and its radius?
I believe the line:
cvCanny(grayscaleImg2, cannyImg2, 0, 255, 3);
should instead be:
cvCanny(imgThreshed, cannyImg2, 0, 255, 3);
because you want to find the contours on the thresholded mask.

How can I detect registration markers on paper using OpenCV?

I've been trying to find the best way to detect the 4 black squares on the paper and use them to isolate the paper in its own image.
It seems that on your image there are only 4 black squares so what you have to do is:
Convert image to grays
Do threshold
Find black contours (before doing this in OpenCV you have to invert your image, because by default OpenCV finds white contours)
Cycle through these contours and find bounding rectangle.
Do the check:
A) Rectangle's area is bigger that some constant (in my solution it was 100)
B) Rectangle's width/height is near 1.0 (in my soultion it was [0.9, 1.1] range)
The code:
Mat img = imread("test.jpg"), gray;
vector<Vec4i> hierarchy;
vector<vector<Point2i> > contours;
cvtColor(img, gray, CV_BGR2GRAY);
threshold(gray, gray, 100, 255, THRESH_BINARY);
bitwise_not(gray, gray);
findContours(gray, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for(size_t i=0; i<contours.size(); i++)
{
Rect rect = boundingRect(contours[i]);
double k = (rect.height+0.0)/rect.width;
if (0.9<k && k<1.1 && rect.area()>100)
{
drawContours(img, contours, i, Scalar(0,0,255));
}
}
imshow("result", img);
waitKey();
Result:
Also read this SO discussion - you don't need that 4 squares to detect paper.

Resources