I've detected the triangular shape of the traffic sign I want to detect. To use this image for further processing, I'd like to create a mask to make the background white (or black, doesn't really matter).
To detect this shape I used:
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
Mat hierarchy = new Mat();
CvInvoke.FindContours(input.GetImage(), contours, hierarchy,Emgu.CV.CvEnum.RetrType.External,Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
With the DrawContours method, I can easily draw them, with the correct result: image of the contours.
How do I make a mask so that I can clear everything outside the contours?
You can use the contours you have and draw to another similar empty image if all what you want is the outline.
If you want to fill, you can use the fillPoly function to fill the contours directly with specified color, and then use the binary filter to make all pixels with that color while and others black.
Related
I am working on a fingerprint recognition project with OpenCV. Currently I need to extract the inner region in fingerprint (ellipse in image), but I am not sure how to do it.
Any suggestion is appreciated.
EDIT:
I need to check if a fingerprint from sensor device and another from identification card match or not. The fingerprint in sensor is as follow (left) meanwhile in identification card is as right fingerprint. In order to validate them, it is required to segment this fingerprint (outside the ellipse doesn't provide useful information but indeed adds "noise" for this purpose).
Thank you.
#API55's comment is correct, for clarity:
create a mask (white inside the ellipse and black outside) you can do this with ellipse function and -1 in the thickness. Then copy the image using the mask (bitwise_and for python or copyTo for c++ should do it)... you will always have a squared image, but you will have black (or the color you want) outside the ellipse
These steps are pretty much spot on,
Create your circular mask in the correct place in the image
Copy the image using that mask
Your new image contains the mask data, and black data everywhere else.
below is an example of how to implement this in code:
( I lovingly borrowed from here)
Mat img = imread("small1.png", 0); // load gray
Rect region(10,10,40,40); // example roi
Mat roi(img, region); // part of img
Mat mask(Size(40,40), CV_8U, Scalar(0)); // all black
circle(mask, Point(20,20), 20, Scalar(255), -1, LINE_AA); // filled circle
Mat circRoi;
bitwise_and(roi, roi, circRoi, mask); // retain only pixels inside the circle
//
// now you can do your intensity calculation on circRoi
//
imshow("circle masked", mask);
imshow("masked roi", circRoi);
waitKey();
Useful Links
Why ROIs don't have to be circular but Mats do
Older code example, useful for learning the theory but I wouldnt recommend implementing using IPLimage
Creating a custom ROI of any shape or size
I have an random shape bitmap cut out by user. I want to fade out its borders i.e. contours, so as to make it appear smooth. What should I do? To get the borders and color of every pixel in bitmap, I am traversing it pixel by pixel. It takes long time, still I am ok with it. Is openCV my only option? If yes, can anybody point me towards any tutorial or suggestion for logical approach?
You can just run a smoothing filter on your shape.
In opencv you can use the blur fnnction or gaussainBlur. Look at http://docs.opencv.org/2.4/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.html.
You don't have to use opencv but i think it would be easier and faster.
If you still don't want can use any other code that implement smoothing an image.
In case you just want to effect the border pixels do the following:
Make a copy of the original image
Filter the entire image.
Extract the border pixel using opencv findContours.
Copy from the blurred image only the pixels in the border and in there neighborhood and copy them to the copy you did in step 1.
I have to remove some lines from the sides of hundreds of grayscale images.
In this image lines appear in three sides.
The lines are not consistent though, i.e, they appear above, below, left and/or right side of the image. And they are of unequal length and width.
If you could assume that the borders are free of important information, you may crop the photo like this:
C++ code:
cv::Mat img;
//load your image into img;
int padding=MAX_WIDTH_HEIGHT_OF_THE LINEAS_AREA
img=img(cv::Rect(padding,padding,img.cols-padding,img.rows-padding));
If not, you have to find a less dumb solution like this for example:
Findcontours
Delete contours that are far from the borders.
Draw contours on blank image
Apply hough line with suitable thresholds.
Delete contours that intersect with lines inside the image border.
Another solution, assuming the handwritten shape is connected:
Findcontours
Get the contour with the biggest area.
Draw it on a blank image with -1(fill) flag in the strock argument.
bitwise_and between the original image and the one you made
Another solution, asuming that the handwritten shape could be discontinuity :
Findcontours
Delete any contour that its all points are very close to the border (using euclidian distance with a threshold)
Draw all remaining contours on a blank image with -1(fill) flag in the strock argument.
bitwise_and between the original image and the one you made
P.S. I did not touch HoughLine transform since I do not about the shapes. I assume that some of them may contain very straight lines.
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 am new to OpenCV and I was trying to extract the region bound by largest contour. It may be a simple question, but I am not able to figure it out. I tried googling too, without any luck.
I would:
Use contourArea() to find the largest closed contour.
Use boundingRect() to get the bounds of that contour.
Draw the contour using drawContours() (with thickness set to -1 to
fill the contour) and use this as a mask.
Use use the mask to set all pixels in the original image not in the
ROI to (0,0,0).
Use the bounding rectangle to extract just that area from the
original image.
Here is well explained what do you want do develop.
Basically you have to:
apply threshold to a copy of the original image;
use findContours -> output is:
vector<vector<Point>>
that stores contours;
iterate on contours to find the largest.