I'm using openCV + C++ to extract the contours of an image.
See these lines:
vector<vector<cv::Point>> contours;
vector<Vec4i> hierarchy;
cvtColor(image, image, CV_BGR2GRAY);
findContours( image, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );
for( int i = 0; i < contours.size(); i++ ) {
// do stuff with contours[i];
}
I was wondering if there is a way to extract the extract the main-color of the image.
From this image --> extract color "blue" as RGB;
Any help how to implement this in C++ would be very appreciated.
Note: This question (Finding contour color using opencv c++) was all I've found during my research but it looks like 1.the question is Off-Topic & 2.the question didn't get answered.
Related
I am creating a stitching program and it works well. My next task is to crop the image so the image doesn't get too large and only contains the stitched areas. I am able to crop the image using the threshold() and findContours() functions. I then parse through the contours to determine where to crop. Another issue I wish to tackle in this function is to set the background to be transparent or alpha(255). My logic is take the base image to crop and do this step in conjunction with finding the area to crop. My code follows with portions that were taken from these two resources:
http://answers.opencv.org/question/37441/how-to-set-transparent-background-to-grabcut-output-image-in-opencv-c/
http://answers.opencv.org/question/24463/how-to-remove-black-background-from-grabcut-output-image-in-opencv-android/#24508
Mat crop(Mat image){
Mat cropped, grayed, thresh, transparent, result;
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
int largest_contour_index=0;
int largest_area=0;
Mat alpha(image.size(),CV_8UC1,Scalar(0));
cvtColor(image, grayed, CV_BGR2GRAY);
threshold( grayed, thresh, 1, 255,THRESH_BINARY);
findContours( thresh, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
vector<int> x,y;
for(int i=0; i < contours.size(); i++){
for(int j = 0; j < contours.at(i).size();j++){
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
}
x.push_back(contours[i][j].x);
y.push_back(contours[i][j].y);
}
}
drawContours( alpha,contours, largest_contour_index, Scalar(255),CV_FILLED, 8, hierarchy );
Mat rgb[3];
split(image,rgb);
Mat rgba[4]={rgb[0],rgb[1],rgb[2],alpha};
merge(rgba,4,transparent);
imshow("Transparent",transparent);
waitKey();
destroyAllWindows();
auto xVals = std::minmax_element(x.begin(), x.end());
auto yVals = std::minmax_element(y.begin(), y.end());
Rect rect (*xVals.first,*yVals.first,(*xVals.second)-(*xVals.first),(*yVals.second)-(*yVals.first));
cropped = image(rect);
return cropped;
}
The following image is the result of this code. As you can see the crop work but the image background is not transparent
Any help is appreciated!
enter image description here
The image shown is the difference between two images. All I want to do is get the location of the white part. I want to do this because I want to be able to highlight the place where the difference is on the original image.
I am thinking about using clustering or blob detection or maybe just locating the brightest or whitest pixel in the image.
What method do you think would be the easiest? Is there another method I haven't though of?
Use the findContour method to find the closed contour in the image.
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours( BinaryImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
And you can draw that contours using drawContours .
And the variable contours contains the coordinates making that particular contour. You can display it by the following command
for(double i=0; i<contours.size(); i++)
{
cout << contours[i];
drawContours( OutputImage, contours, i, Scalar(0,255,0), 2, 8, hierarchy, 0, Point() );
}
I have a photo where a person holds a sheet of paper. I'd like to detect the rectangle of that sheet of paper.
I have tried following different tutorials from OpenCV and various SO answers and sample code for detecting squares / rectangles, but the problem is that they all rely on contours of some kind.
If I follow the squares.cpp example, I get the following results from contours:
As you can see, the fingers are part of the contour, so the algorithm does not find the square.
I, also, tried using HoughLines() approach, but I get similar results to above:
I can detect the corners, reliably though:
There are other corners in the image, but I'm limiting total corners found to < 50 and the corners for the sheet of paper are always found.
Is there some algorithm for finding a rectangle from multiple corners in an image? I can't seem to find an existing approach.
You can apply a morphological filter to close the gaps in your edge image. Then if you find the contours, you can detect an inner closed contour as shown below. Then find the convexhull of this contour to get the rectangle.
Closed edges:
Contour:
Convexhull:
In the code below I've just used an arbitrary kernel size for morphological filter and filtered out the contour of interest using an area ratio threshold. You can use your own criteria instead of those.
Code
Mat im = imread("Sh1Vp.png", 0); // the edge image
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(11, 11));
Mat morph;
morphologyEx(im, morph, CV_MOP_CLOSE, kernel);
int rectIdx = 0;
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(morph, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
for (size_t idx = 0; idx < contours.size(); idx++)
{
RotatedRect rect = minAreaRect(contours[idx]);
double areaRatio = abs(contourArea(contours[idx])) / (rect.size.width * rect.size.height);
if (areaRatio > .95)
{
rectIdx = idx;
break;
}
}
// get the convexhull of the contour
vector<Point> hull;
convexHull(contours[rectIdx], hull, false, true);
// visualization
Mat rgb;
cvtColor(im, rgb, CV_GRAY2BGR);
drawContours(rgb, contours, rectIdx, Scalar(0, 0, 255), 2);
for(size_t i = 0; i < hull.size(); i++)
{
line(rgb, hull[i], hull[(i + 1)%hull.size()], Scalar(0, 255, 0), 2);
}
I want to find points of a contour which is draw on object after following operation like background subtraction , findcontour ,drawcontour.
My object is moving so that my contour is also not proper . and i want to find of maximum and minimum points on contour which is draw on object.
Can anyone tell me how to find?
My object is moving car and camera view is top.
vector<vector<Point>> allContours;
vector<Vec4i> hierarchy;
Mat _temp = image.clone();
findContours(_temp, allContours, RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
allContours is contour's vector.
you can access points of each contours.
============================================================================
all points of contous will be draw by below code.
vector<vector<Point>> allContours;
vector<Vec4i> hierarchy;
Mat _temp = imageGray.clone();
Mat ptDraw = Mat::zeros(image.rows,image.cols,CV_8UC3);
findContours(_temp, allContours, RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for(int i=0;i<allContours.size();i++)
{
drawContours(image, allContours, i, Scalar(0,0,255), 2, 8, hierarchy, 0, Point() );
for(int j=0;j<allContours.at(i).size();j++)
{
Point pt = allContours.at(i).at(j);
circle(ptDraw,pt,1,Scalar(0,0,255),CV_FILLED);
}
}
I want use findContours with the binary image, but the callback function causes an error:
Invalid address specified to RtlFreeHeap
when returning.
When i want to use clear() to free the vector<vector<Point> > value, it causes the same exception and the code crashed in free.c at the line:
if (retval == 0) errno = _get_errno_from_oserr(GetLastError());
For example:
void onChangeContourMode(int, void *)
{
Mat m_frB = imread("3.jpg", 0);
vector<vector<Point>> contours
vector<Vec4i> hierarchy;
findContours(m_frB, contours, hierarchy, g_contour_mode, CV_CHAIN_APPROX_SIMPLE);
for( int idx = 0 ; idx >= 0; idx = hierarchy[idx][0] )
drawContours( m_frB, contours, idx, Scalar(255,255,255),
CV_FILLED, 8, hierarchy );
imshow( "Contours", m_frB );
}
Can anyone help me? Thank you very much!
Mat m_frB = imread("3.jpg", CV_LOAD_IMAGE_GRAYSCALE);
loads 3.jpg as a 8bpp grayscale image, so it's not binary image. It is specific for findContours function that "non-zero pixels are treated as 1’s. Zero pixels remain 0’s, so the image is treated as binary". Also note that this "function modifies the image while extracting the contours".
The actual problem here is that although the destination image is 8bpp, you should make sure that it has 3 channels by using CV_8UC3 before you draw RGB contours into it. Try this:
// find contours:
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(m_frB, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE);
// draw contours:
Mat imgWithContours = Mat::zeros(m_frB.rows, m_frB.cols, CV_8UC3);
RNG rng(12345);
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(rng.uniform(50, 255), rng.uniform(50,255), rng.uniform(50,255));
drawContours(imgWithContours, contours, i, color, 1, 8, hierarchy, 0);
}
imshow("Contours", imgWithContours);