opencv crop a portion of image within contour - c++

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
}
}

Related

extract largest contour from set of contours open cv

After reading some stack overflow posts on image processing, I made a program to detect and a paper in an image and remove the background. But currently the program only detects the contours. How can I crop out the biggest contour? Eventually, I will use this region and use tesseract for character recognition. I am stuck at the preprocessing part.
the image I used:
And this is what I got after running my script:
How can I approximate the big blue contour and crop it out for things like character detection?
Here is the code I used:
static void on_canny( int,void* ){
blur( dst, detected_edges, Size(3,3) );
Canny(detected_edges, detected_edges, cannyThreshold, cannyThreshold*r, kernel_size);
findContours(detected_edges, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
Mat drawing = Mat::zeros( detected_edges.size(), CV_8UC3 );
for(int i=0;i<contours.size();i++)
{
Scalar color = Scalar( rng.uniform(0, 255), rng.uniform(0,255), rng.uniform(0,255) );
drawContours( drawing, contours, i, color, 2, 8, hierarchy, 0, Point() );
}
imshow("Contour",drawing);
imshow("Canny", detected_edges);
}

OpenCV detect & extract text in images

I am working on reading container code using an IP Camera and I came across #dhanushka's gradient based method for text detection and I've been successful with it as you can see below...
bool debugging = true;
Mat rgb = imread("/home/brian/qt/ANPR/images/0.jpg", 0);
if(debugging) { imshow("Original", rgb); }
Mat grad;
Mat morphKernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
morphologyEx(rgb, grad, MORPH_GRADIENT, morphKernel);
if(debugging) { imshow("gradient morph", grad); }
// binarize
Mat bw;
threshold(grad, bw, 0.0, 255.0, THRESH_BINARY | THRESH_OTSU);
if(debugging) { imshow("threshold", bw); }
// connect horizontally oriented regions
Mat connected;
morphKernel = getStructuringElement(MORPH_RECT, Size(10, 1));
morphologyEx(bw, connected, MORPH_CLOSE, morphKernel);
if(debugging) { imshow("horizontal regions morph", connected); }
// find contours
Mat mask = Mat::zeros(bw.size(), CV_8UC1);
vector<vector<Point> > contours2;
vector<Vec4i> hierarchy;
vector<Rect> txtRect;
vector<vector<Point> > txtContour;
findContours(connected, contours2, hierarchy, CV_RETR_CCOMP,
CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
// filter contours
for(int i = 0; i >= 0; i = hierarchy[i][0]) {
Rect rect = boundingRect(contours2[i]);
Mat maskROI(mask, rect);
maskROI = Scalar(0, 0, 0);
// fill the contour
drawContours(mask, contours2, i, Scalar(255, 255, 255), CV_FILLED);
// ratio of non-zero pixels in the filled region
double r = (double)countNonZero(maskROI)/(rect.width*rect.height);
/* assume at least 45% of the area is filled if it contains text */
if (r > .45 && (rect.height > 10 && rect.width > 10)) {
rectangle(rgb, rect, Scalar(0, 255, 0), 2);
txtRect.push_back(rect);
txtContour.push_back(contours2[i]);
}
}
if(debugging) { imshow("Characters", rgb); }
Mat text(rgb.size(), CV_8U, Scalar(255));
drawContours(text, txtContour, -1, Scalar(0), FILLED, 4);
if(debugging) { imshow("Detected Text", text); }
Step 0: Original Image
Step 1: Morphological gradient
Step 2: Binarized image
Step 3: Horizontally oriented regions
Step 4: Detected Text
Step 5: Extracted Text
The problem is that I have failed to properly extract the detected text so that I can use it in OCR to get the result BSIU225378.
The text I managed to extract is coming from the horizontal connected regions and its unusable for orc, is there a way I can extract text say from the binarized (threshold) image using the contours I found in the horizontal connected regions?

crop triangle from blackbackground

I'm new to image processing and development.I have a triangle in black background. I want to save that triangle as a Mat object without black pixels[0]. In order to do I tried as below.
Set threshold
find contours
identify contour[0] as trangle // has 2 contours one is triangle other one is backpixels.
save the contour points
crop the image.
My code please find below.
Mat finalImage = imread("test.png, CV_LOAD_IMAGE_GRAYSCALE);
img.copyTo(finalImage, mask);
Mat canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
int thresh = 100;
int max_thresh = 255;
RNG rng(12345);
/// Detect edges using canny
Canny(finalImage, canny_output, thresh, thresh * 2, 3);
/// Find contours
findContours(canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); //find this method
/// Draw contours
Mat drawing = Mat::zeros(canny_output.size(), CV_8UC1);
for (int i = 0; i< contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point()); // find this method.
}
I have points of contour but by using points of contours i have no idea how to crop only the trangle in input image.
You can get the bounding Rect of the various contours at the same time you are re drawing the contours. So in Your for loop where you are iterating the contours, you may use cv::boundingRect() to get the bounding Rect of the respective contour as:
/// Draw contours
Mat drawing = Mat::zeros(canny_output.size(), CV_8UC1);
for (int i = 0; i< contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point()); // find this method.
cv::Rect boundingRect = cv::boundingRect(contours[i]);
}

OpenCV remove/cover specific contours

I have a video that I want to remove some specific contours on, I capture the video and then draw all the contours;
//Prepare the image for findContours
cv::cvtColor(frame, frame, CV_BGR2GRAY);
cv::threshold(frame, frame, 128, 255, CV_THRESH_BINARY);
//Find the contours. Use the contourOutput Mat so the original image doesn't get overwritten
std::vector<std::vector<cv::Point> > contours;
cv::Mat contourOutput = frame.clone();
cv::findContours( contourOutput, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE );
//Draw the contours
cv::Mat contourImage(frame.size(), CV_8UC3, cv::Scalar(0,0,0));
cv::Scalar colors[3];
colors[0] = cv::Scalar(255, 0, 0);
colors[1] = cv::Scalar(0, 255, 0);
colors[2] = cv::Scalar(0, 0, 255);
for (size_t idx = 0; idx < contours.size(); idx++) {
cv::drawContours(contourImage, contours, idx, colors[idx % 3]);
}
The result looks like this:
Contours
So what I want to do now is to remove or cover objects like the trees and the tall house, basically contours that have a more complex shape than a road sign etc.
A desired result would look like this:
Removed/covered contours
It doesn't have to be exactly like on the picture as long as I can get something I can play with.

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);