原文链接:http://answers.opencv.org/question/134783/android-opencv-finding-extreme-points-in-contours/
导 读:本例子使用轮廓分析,寻找到轮廓的极点;使用了STD的SORT特性。
提出问题:
Good Evening,
I have a trouble with finding extreme points in frames. I am detecting all contours, but I want find there one extreme point, which is lowest from others (southernmost contour). Here is a preview of screen, what I have.
And here is a preview of screen, what I want ! For example, lowest point will bounded by red rectangle.
.
And here is my code, what I have now.
contours
=
new ArrayList
<MatOfPoint
>();
Rect rect;
Point c1 = new Point(); Point c2 = new Point();
Imgproc.cvtColor(mRgba, mGray, Imgproc.COLOR_RGB2GRAY);
subtractorMOG2.apply(mGray, mFGMask, 0. 005);
Imgproc.threshold(mFGMask, mFGMask, 45, 255, Imgproc.THRESH_BINARY);
Imgproc.erode(mFGMask, mFGMask, new Mat());
Imgproc.dilate(mFGMask, mFGMask, new Mat());
Imgproc.findContours(mFGMask, contours, new Mat(), Imgproc.RETR_EXTERNAL , Imgproc.CHAIN_APPROX_NONE);
Imgproc.drawContours(mRgba, contours, - 1, new Scalar( 255, 255, 0), 3);
/*for (int idx = 0; idx < contours.size(); idx++) {
double contourarea = Imgproc.contourArea(contours.get(idx));
rect = boundingRect(contours.get(idx));
c1.x = rect.x; c1.y = rect.y;
c2.x = rect.x + rect.width; c2.y = rect.y + rect.height;
if (contourarea > 1024 && contourarea < 30000) {
Imgproc.rectangle(mRgba, c1, c2, new Scalar(255, 0, 0), 3);
}
}*/
return mRgba;
Rect rect;
Point c1 = new Point(); Point c2 = new Point();
Imgproc.cvtColor(mRgba, mGray, Imgproc.COLOR_RGB2GRAY);
subtractorMOG2.apply(mGray, mFGMask, 0. 005);
Imgproc.threshold(mFGMask, mFGMask, 45, 255, Imgproc.THRESH_BINARY);
Imgproc.erode(mFGMask, mFGMask, new Mat());
Imgproc.dilate(mFGMask, mFGMask, new Mat());
Imgproc.findContours(mFGMask, contours, new Mat(), Imgproc.RETR_EXTERNAL , Imgproc.CHAIN_APPROX_NONE);
Imgproc.drawContours(mRgba, contours, - 1, new Scalar( 255, 255, 0), 3);
/*for (int idx = 0; idx < contours.size(); idx++) {
double contourarea = Imgproc.contourArea(contours.get(idx));
rect = boundingRect(contours.get(idx));
c1.x = rect.x; c1.y = rect.y;
c2.x = rect.x + rect.width; c2.y = rect.y + rect.height;
if (contourarea > 1024 && contourarea < 30000) {
Imgproc.rectangle(mRgba, c1, c2, new Scalar(255, 0, 0), 3);
}
}*/
return mRgba;
Thanks everybody for help and comments !
优质解答:
bool
SortbyXaxis(
const
Point
&
a,
const
Point
&
b)
{
return a.x > b.x;
}
bool SortbyYaxis( const Point & a, const Point &b)
{
return a.y > b.y;
}
int main ( int argc, char * const argv[])
{
Mat mSrc,mDst;
mSrc = imread( "e:/sandbox/aline.png", 0);
if (mSrc.empty())
{
cerr << "No image supplied ..." << endl;
return - 1;
}
cvtColor(mSrc,mDst,COLOR_GRAY2BGR);
/// Create Window
const char * source_window = "Output Image";
namedWindow( source_window, WINDOW_AUTOSIZE );
vector <vector <Point > > contours;
vector <Vec4i > hierarchy;
/// Find contours
findContours( mSrc.clone(), contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point( 0, 0) );
vector <Point > ptsContour;
for( size_t i = 0; i < contours.size(); i ++ )
{
drawContours( mDst, contours, ( int)i, Scalar( 0, 255, 0), 1);
ptsContour = contours[i];
sort( ptsContour.begin(), ptsContour.end(), SortbyYaxis );
sort( ptsContour.begin(), ptsContour.end(), SortbyXaxis );
circle(mDst, ptsContour[ 0], 3,Scalar( 0, 255, 255), - 1);
}
imshow( source_window, mDst );
waitKey();
return 0;
}
{
return a.x > b.x;
}
bool SortbyYaxis( const Point & a, const Point &b)
{
return a.y > b.y;
}
int main ( int argc, char * const argv[])
{
Mat mSrc,mDst;
mSrc = imread( "e:/sandbox/aline.png", 0);
if (mSrc.empty())
{
cerr << "No image supplied ..." << endl;
return - 1;
}
cvtColor(mSrc,mDst,COLOR_GRAY2BGR);
/// Create Window
const char * source_window = "Output Image";
namedWindow( source_window, WINDOW_AUTOSIZE );
vector <vector <Point > > contours;
vector <Vec4i > hierarchy;
/// Find contours
findContours( mSrc.clone(), contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point( 0, 0) );
vector <Point > ptsContour;
for( size_t i = 0; i < contours.size(); i ++ )
{
drawContours( mDst, contours, ( int)i, Scalar( 0, 255, 0), 1);
ptsContour = contours[i];
sort( ptsContour.begin(), ptsContour.end(), SortbyYaxis );
sort( ptsContour.begin(), ptsContour.end(), SortbyXaxis );
circle(mDst, ptsContour[ 0], 3,Scalar( 0, 255, 255), - 1);
}
imshow( source_window, mDst );
waitKey();
return 0;
}
程序解读:本程序的基本思路是很简答的,就是遍历轮廓,找到轮廓中x和y最大的点,这个点就是极值点。但是有两个地方需要注意:
1、是使用了std的sort特性,应该说简化了程序设计;
2、是findcontours的第二个参数,使用的是“只寻找第一层轮廓”。那么对于本例来说,这样做是合理的。