我的方法有点简单,通过考虑前两行,如果两个点的质心位于同一垂直线上,则为正方形,否则为菱形。在这里您需要执行以下步骤。
- 在图片中找到contours。
- 使用moments 查找每个轮廓的质心。
- 现在您需要按照从左上到右下的顺序对质心进行排序。
- 仅取前两行并检查第一行到第二行中的每个质心,因为它的 x 坐标相等,即检查这些行中的任何两个点是否位于同一垂直线上,如果是,则为正方形,否则为菱形.
您也可以参考下面的 C++ 代码。
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace cv;
using namespace std;
int tolerance=3; /// You can varies this to change the result as the centroid may varies in little even if it's lies in same vertical line
///For sorting x,y co-ordinates from top left corner to bottom rgiht corner
struct sort_xy {
bool operator() (cv::Point pt1, cv::Point pt2) {
if((pt2.y-tolerance<=pt1.y)&&(pt1.y<=pt2.y+tolerance)) return (pt1.x < pt2.x); ///if y values are equal sort x
else return (pt1.y < pt2.y); /// else sort y
}
} compare_xy;
int main(){
Mat tmp,thr;
Mat src=imread("1.png",1);
cvtColor(src,tmp,CV_BGR2GRAY);
threshold(tmp,thr,10,255,THRESH_BINARY_INV);
imshow("thr,",thr);
///Find contours
vector< vector <Point> > contours; // Vector for storing contour
vector< Vec4i > hierarchy;
int largest_contour_index=0;
int largest_area=0;
Mat dst(src.rows,src.cols,CV_8UC3,Scalar::all(0)); //create destination image
findContours( thr, contours, hierarchy,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE ); // Find the contours in the image
/// Get the moments and mass centers:
vector<Moments> _moment(contours.size() );
vector<Point> centroid( contours.size() );
for( int i = 0; i < contours.size(); i++ ) {
_moment[i] = moments( contours[i], false );
centroid[i] = Point( _moment[i].m10/_moment[i].m00 ,_moment[i].m01/_moment[i].m00 );
}
/// Sort centroid of each contour from top left to bottom right
sort(centroid.begin(), centroid.end(), compare_xy);
///Draw all sorted centroid to dst image
for( int i = 0; i <centroid.size(); i++ ) {
circle(dst, centroid[i], 3,Scalar(0,255,0),1,CV_AA, 0);
imshow("dst",dst);
}
/// Store first two rows of centroid to a vector
vector< vector <Point> > rows(2);
int j=0;
for( int i = 0; i < centroid.size(); i++ ) {
if((centroid[i+1].y-tolerance<=centroid[i].y)&&(centroid[i].y<=centroid[i+1].y+tolerance))
rows[j].push_back(centroid[i]);
else j++;
if(j>1) i = centroid.size();
}
/// This block will decide whether the image is Squre or Rhombic.
/// The loop checks whether any x-coordinates centroid in first row is equal to
/// x-coordinates centroid in second row, if so it is squre otherwise Rhombic.
/// That is it simply checks whether two centroid lies in same vertical line.
int cnt=0;
if(rows[0].size()>rows[1].size()) cnt=rows[1].size();
else cnt=rows[0].size();
int squre=0;
for( int i = 0; i <cnt; i++ ){
for( int j = 0; j <cnt; j++ ){
if((rows[1][j].x-tolerance<=rows[0][i].x)&&(rows[0][i].x<=rows[1][j].x+tolerance))
squre++;
}
}
/// Show the result
if(squre > 0) putText(dst,"Squre", Point(50,50), FONT_HERSHEY_SIMPLEX,1, Scalar (0,0,255), 3, 8,false );
else putText(dst,"Rhombic ", Point(50,50), FONT_HERSHEY_SIMPLEX,1, Scalar (0,0,255), 3, 8,false );
imshow("src,",src);
imshow("dst",dst);
waitKey();
return 0;
}
这里我为你的图片找到了一些结果
图片 1
图片 2
图 3