I am developing face features detection in my project.
Heretofore i have developed detecting the face, then finding the eyes within the face.
I want to crop the eyes which are in circular .
circle( mask, center, radius, cv::Scalar(255,255,255), -1, 8, 0 );
image.copyTo( dst, mask );
Here in the above code , I am able to Mask image with black color leaving eye region. now I am want to crop only the Eye region.
Can anybody help me out on this issue.Please check below image
Cropping, by definition, means cutting an axis aligned rectangle from a larger image, leaving a smaller image.
If you want to "crop" a non-axis-aligned rectangle, you will have to use a mask. The mask can be the size of the full image (this is sometimes convenient), or as small and the smallest bounding (axis-aligned) rectangle containing all the pixels you want to leave visible.
This mask can be binary, meaning that it indicates whether or not a pixel is visible, or it can be an alpha-mask which indicated the degree of transparency of any pixel within it, with 0 indicating a non-visible pixel and (for 8-bit mask image) 255 indicating full opacity.
In your example above you can get the sub-image ROI (Region-Of-Interest) like this:
cv::Mat eyeImg = image(cv::Rect(center.x - radius, // ROI x-offset, left coordinate
center.y - radius, // ROI y-offset, top coordinate
2*radius, // ROI width
2*radius)); // ROI height
Note that eyeImg is not a copy, but refers to the same pixels within image. If you want a copy, add a .clone() at the end.
Related
I'm trying to build an algorithm that calculates the dimensions of slabs (in pixel units as of now). I tried masking, but there is no one HSV color range that will work for all the test cases, as the slabs are of varying colors. I tried Otsu thresholding as well but it didn't work quite well...
Now I'm trying my hand with canny edge detection. The original image, and the image after canny-edge look like this:
I used dilation to make the central region a uniform white region, and then used contour detection. I identified the contour having the maximum area as the contour of interest. The resulting contours are a bit noisy, because the canny edge detection also included some background stuff that was irrelevant:
I used cv2.boundingRect() to estimate the height and width of the rectangle, but it keeps returning the height and width of the entire image. I presume this is because it works by calculating (max(x)-min(x),max(y)-min(y)) for each (x,y) in the contour, and in my case the resulting contour has some pixels touching the edges of the image, and so this calculation simply results in (image width, image height).
I am trying to get better images to work with, but assuming all images are like this only, i.e. have noisy contours, what can be an alternate approach to detect the dimensions of the white rectangular region obtained after dilating?
To get the right points of the rectangle use this:
p = cv2.arcLength(cnt True) # cnt is the rect Contours
appr = cv2.approxPolyDP(cnt , 0.01 * p, True) # appr contains the 4 points
# draw the rect
cv2.drawContours(img, [appr], 0, (0, 255, 0), 2)
The appr var contains the turning point of the rect. You still need to do some more cleaning to get better results, but cv2.boundingRect() is not a good solution for your case.
Hi guys, I would want to find the corners of this calibration card, to enable scaling and geometric calibration. The image above is the grid I am referring to.
Shown is the full image, and I want the corners detected for the black and white grid.
However, when I try to run
gray = cv2.cvtColor(image_cal, cv2.COLOR_BGR2GRAY) #image_cal is the image to be calibrated
cv2_imshow(gray)
retval, corners = cv2.findChessboardCorners(gray, (3, 4))
The retval returns false, meaning no chessboard is detected.
I have tried different pictures but it seems they all cannot be detected.
Then I turn to Harrison Corner Detection,
gray = np.float32(gray)
# bi = cv2.bilateralFilter(gray, 5, 75, 75)
# blurred = cv2.filter2D(gray,-1,kernel)
dst = cv2.cornerHarris(gray,2,3,0.04)
dst = cv2.dilate(dst, None)
image_cal[dst>0.01*dst.max()]=[0,0,255]
cv2_imshow(image_cal)
Which gives me many corners, but I cannot accurately just narrow down to only the black and white grid corners.
Also, there is no guarantee the next image to be fed will still have the black and white grid in the same position so I cannot use some location boundaries to limit the search.
Eventually I would want to know the coordinates of the corners and their corresponding mapped coordinates (such that the target coordinates are properly spaced in distance according to the grid e.g. adjacent vertical or horizontal corners are 1cm apart, without distortion), and feed into a findHomography function of opencv.
Appreciate any help!
Hi , I have attached the image below with an yellow bounding box. Is there any algorithm or (sequence of algorithms) in Opencv by which I can detect the yellow pixels and create a ROI mask (which will block out all the pixels outside of it).
You can do:
Find the yellow polygon
Fill the inside of the polygon
Copy only the inside of the polygon to a black-initialized image
Find the yellow polygon
Unfortunately, you used anti-aliasing to draw the yellow line, so the yellow color is not pure yellow, but has a wider range due to interpolation. This affects also the final results, since some not yellow pixels will be included in the result image. You can easily correct this by not using anti-aliasing.
So the best option is to convert the image in the HSV space (where it's easier to segment a single color) and keep only values in a range around the pure yellow.
If you don't use anti-aliasing, you don't even need to convert to HSV and simply keep points whose value is pure yellow.
Fill the inside of the polygon
You can use floodFill to fill the polygon. You need a starting point for that. Since we don't know if a point is inside the polygon (and taking the baricenter may not be safe since the polygon is not convex), we can safely assume that the point (0,0), i.e. the top-left corner of the image is outside the polygon. We can then fill the outside of the polygon, and then invert the result.
Copy only the inside of the polygon to a black-initialized image
Once you have the mask, simply use copyTo with that mask to copy on a black image the content under non-zero pixels in the mask.
Here the full code:
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
Mat3b img = imread("path_to_image");
// Convert to HSV color space
Mat3b hsv;
cvtColor(img, hsv, COLOR_BGR2HSV);
// Get yellow pixels
Mat1b polyMask;
inRange(hsv, Scalar(29, 220, 220), Scalar(31, 255, 255), polyMask);
// Fill outside of polygon
floodFill(polyMask, Point(0, 0), Scalar(255));
// Invert (inside of polygon filled)
polyMask = ~polyMask;
// Create a black image
Mat3b res(img.size(), Vec3b(0,0,0));
// Copy only masked part
img.copyTo(res, polyMask);
imshow("Result", res);
waitKey();
return 0;
}
Result:
NOTES
Please note that there are almost yellow pixels in the result image. This is due to anti-aliasing, as explained above.
I have a simple colorful image taken by camera, and I need to detect some 'Red' circles inside of it very accurate.Circles have different radius and they should be distinguishable. There are some black circles in the photo also.
Here is the procedure I followed:
1 - Convert from RGB to HSV
2 - Determining "red" upper and lower band:
lower_red = np.array([100, 50, 50])
upper_red = np.array([179, 255, 255])
3 - Create a mask.
4 - Applying cv2.GaussianBlur to smoothing the mask and noise reduction.
5 - Detecting remaining circles by using 'cv2.HoughCircles' on 'Mask' functions with different radius. (I have radius range)
Problem: When I create mask, the quality is not good enough, therefore Circles are detected wrong according to their radius.
Attachments include main photo, mask, and detected circles.
Anybody can help to set all pixels to black appart red pixels. Or in the other words, creating a high quality mask.
My application requires mapping one quadrilateral to another quadrilateral. Neither of these are rectangles.
However, the result I get from warpPerspective() is always a rectangle. I have tried setting the "outlier" flag to different values to prevent pixels from outside the warped quad from appearing in the destination image but nothing seems to work. What I want is a warped quad with the pixels outside the warped quad set to transparency.
How do I achieve this?
Alternatively, is there a straightforward way to mask the region outside a quadrilateral in OpenCV so that I can copy just the quad to another image?
In case it is relevant, I am using the Python binding to OpenCV.
Here is my current code:
def warpImage(image, corners, target, width, height):
mat = cv2.getPerspectiveTransform(corners, target)
out = numpy.zeros(shape=(width, height), dtype="uint8")
out = cv2.warpPerspective(image, mat, (width,height), out, cv2.INTER_CUBIC)
return out
corners and target are both non-rectangular quads. The output is a full widthxheight rectangle, however. None of the pixels are black or transparent. Instead they are pixels from the image both inside and outside the corners quad. I only want the ones inside.
The best option I have found is to cycle through the pixels and copy the ones in the warped quad to a remap array using the matplotlib pnpoly() function, as so:
import matplotlib.nxutils as nx
def warpImage(image, corners, target, width, height, x0, y0, remap):
mat = cv2.getPerspectiveTransform(corners, target)
out = cv2.warpPerspective(image, mat, (width,height), flags=cv2.INTER_CUBIC)
for x in range(0,width):
for y in range(0,height):
if nx.pnpoly(x,y,target) == 1:
for i in range(0,3):
remap[y+y0,x+x0,i] = out[y,x,i]
return remap
I loop through all the quads in image and accumulate transformed versions in remap.
Having to access each pixel is not very efficient but fortunately this is a one time transformation.