Converting contours from vector of cv::Point in cv::Mat - c++

Suppose my objective is to extract contours from an initial image. I performed this operations using OpenCV:
cv::Mat gray, edges;
cv::cvtColor(image, gray, CV_BGRA2GRAY);
cv::Canny(gray, edges, 100, 300, 3);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(edges, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
Now the contour is contained in an array of Points. I want to rebuild a cv::Mat structure having the same dimensions as the initial image, so as to emphasize the contour by superimposing it to the image.
In particular, I am not interested in drawing immediately the contour. I will perform the following operations:
extract the contour
dilate the contour
superimpose the contour on the image (as you do in edge sharpening)
Thus, the contour has to be a matrix of the same size of the input image.
How can I do that?
Thanks in advance.

You can re-built a Matrix
Mat image_contours_grayscale = Mat::zeros(gray.size(),gray.type());
Scalar color(255);
drawContours( image_contours_grayscale, contours,-1,color,1);
I'm not sure if drawContours works with grayscale image, but if it doesn't, you can try this
Mat image_contours_color = Mat::zeros(image.size(),image.type());
Scalar color(255,255,255);
drawContours( image_contours_color, contours,-1,color,1);
Mat image_contours_grayscale;
cv::cvtColor(image_contours_color, image_contours_grayscale, CV_BGRA2GRAY);
image_contours_grayscale should be a grayscale image, all black with the contours in white.
Let me know if this works, I didn't have the occasion to test this solution !

Related

detect defects which are grayish in color from the image

I need to detect the defects which are more grayish in color.
I have tried removing noise from the image, thresholding the image but due to gray color of the defect, it becomes invisible or only the boundary remains. I don't know how to detect the defects , if I apply dilation it gets mixed with the surrounding circles.
Images with defects:
Images without defect:
My original image with the red pen marked defect is :
I have tried the below code:
//convert to grayscale
Mat gray_img;
cv::cvtColor(r_img, gray_img, COLOR_BGR2GRAY);
Mat dst1, dst2, dst;
cv::blur(gray_img, dst1, Size(3, 3));
cv::blur(gray_img, dst2, Size(7, 7));
cv::subtract(dst1, dst2, dst);
//thresholding
Mat thresh;
adaptiveThreshold(dst, thresh, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 5, 5);
Mat inv_thresh;
bitwise_not(thresh, inv_thresh);
My thresholded image is

OpenCV - how many black objects are there in a photo?

Okay, so I'm trying openCV with c++, and I want to do a simple detection program for objects that are black colored. So I have this simple code:
int main()
{
Mat3b bgr = imread("C:/Users/sesoa/Desktop/photos/shapes.png");
Mat3b hsv;
cvtColor(bgr, hsv, COLOR_BGR2HSV);
Mat1b mask1, mask2;
inRange(hsv, Scalar(0, 0, 0, 0), Scalar(180, 255, 30, 0), mask1);
inRange(hsv, Scalar(0, 0, 0, 0), Scalar(180, 255, 40, 0), mask2);
Mat1b mask = mask1 | mask2;
imshow("Mask", mask);
waitKey();
return 0;
}
shapes.png is this:
all the shapes are rounded with color black. I would like for my program to tell me how many of connected black objects are there. Also the writing under the shapes is also black. So It shows me this as well, that's okay, cause this is a test photo anyway.
How can I modify my program to detect how many connected black objects are in the photo? (In this photo, the output should be "60" as there are 8 objects and 49 letters + 3 letters are 'i' so we have to count the dots).
EDIT:
I want the program to count black objects. I already get all black objects out like this:
If you want to count the number of objects just do the following:
std::vector<std::vector<cv::Point> > contours;
std::vector<cv::Vec4i> hierarchy;
findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) ); // canny_output is the binary image
This will give you all the contours in the binary image (contours.size()). If you want only specific contours you can filter with contour area.
Hope it helps!

opencv crop a portion of image within contour

I've just started learning OpenCv. i wanted to crop a portion of an image which is a text surrounded by the red circle. can you guys help me to find the solution like what are all the methods i should follow to crop it. I've tried few things and got the red circle cropped and stored it in a mat.
while(1)
{
capture>>img0;
imshow("original", img0);
imwrite("original.jpg", img0);
cv::inRange(img0,cv::Scalar(0,0,100),cv::Scalar(76,85,255),img1);
imshow("threshold.jpg", img1);
imwrite("threshold.jpg", img1);
// find the contours
vector< vector<Point> > contours;
findContours(img1, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
Mat mask = Mat::zeros(img1.rows, img1.cols, CV_8UC1);
drawContours(mask, contours, -1, Scalar(255), CV_FILLED);
Mat crop(img0.rows, img0.cols, CV_8UC3);
crop.setTo(Scalar(255,255,255));
img0.copyTo(crop, mask);
normalize(mask.clone(), mask, 0.0, 255.0, CV_MINMAX, CV_8UC3);
imshow("mask", mask);
imshow("cropped", crop);
imwrite("mask.jpg", mask);
imwrite("cropped.jpg", crop);
if(waitKey(30)=='27')
{
break;
}
}
return 0;`[original image[cropped image][1]`
From this image i wanted to crop a text alone. do help me to find the solution by sharing me the methods or steps to follow.
Thanks in advance
If you wish to extract the text alone, you can try this:-
drawContours(mask, contours, -1, Scalar(255), CV_FILLED);
vector<Rect> boundRect( contours.size() );
for(int i=0;i<contours.size();i++)
{
boundRect[i] = boundingRect(contours[i]);//enclose in Rect
Mat ROI,ROI_txt;
if(boundRect[i].width>30 && boundRect[i].height>30)//ignore noise rects
{
ROI=img0(boundRect[i]);//extract Red circle on ROI
inRange(ROI,Scalar(0,0,0),cv::Scalar(50,50,50),ROI_txt);
//black colour threshold to extract black text
}
}

Opencv findcontours CV_RETR_EXTERNAL not working

I've this image:
EDIT
Sorry but I had to remove the images!
I need to extract the contour of the non-black picture, so I used findcontour with the CV_RETR_EXTERNAL parameter, but I obtain this:
Here's the code:
static Mat canny_output, grey,draw;
vector<vector<Point>> contours;
cvtColor(final_img, grey, CV_BGR2GRAY);
Canny(grey, canny_output, 100, 200);
findContours(canny_output, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
draw = Mat::zeros(canny_output.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); i++)
{
drawContours(draw, contours, i, Scalar(255, 0, 0));
}
how can I resolve?
Simply add a binarization with minimal threshold, and remove Canny:
cvtColor(final_img, grey, CV_BGR2GRAY);
//Threshold=1: very low value, anyway the rest of the image is pure black
threshold(grey, binary, 1, 255, CV_THRESH_BINARY);
findContours(binary, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

Find and draw largest rect OpenCV

I need to find the largest contour/rect on this image which should be the card.
I try to use the following code but I get no drawing:
int largest_area=0;
int largest_contour_index=0;
cv::Rect bounding_rect;
Mat thr(src.rows,src.cols,CV_8UC1);
Mat dst(src.rows,src.cols,CV_8UC1,Scalar::all(0));
cvtColor(src,thr,CV_BGR2GRAY); //Convert to gray
threshold(thr, thr,25, 255,THRESH_BINARY); //Threshold the gray
vector<vector<cv::Point>> contours; // Vector for storing contour
vector<Vec4i> hierarchy;
findContours( thr, contours, hierarchy,CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image
for( int i = 0; i< contours.size(); i++ ) // iterate through each contour.
{
double a=contourArea( contours[i],false); // Find the area of contour
if(a>largest_area){
largest_area=a;
largest_contour_index=i; //Store the index of largest contour
bounding_rect=boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
}
}
Scalar color( 255,255,255);
drawContours( dst, contours,largest_contour_index, color, CV_FILLED, 8, hierarchy ); // Draw the largest contour using previously stored index.
rectangle(src, bounding_rect, Scalar(0,255,0),1, 8,0);
Could someone provide me with an example using this image to find the largest rect?
You can try yourself by increasing the threshold.
Here You are finding biggest contour on thresholded image, so display thr just after threshold() using imshow() and see what going on , and how it's look like.
See the result by increasing the threshold to little higher value.
threshold(thr, thr,100, 255,THRESH_BINARY); //Threshold the gray
Threshold image
Bounding rect for biggest contour