在debug模式下可以正常运行 release下也编译通过
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
double getAngle(Point pt1, Point pt2, Point pt0)
{
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1*dx2 + dy1*dy2) / sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}
bool isYellowSquare(Mat image_H, vector<Point> square)
{
int pointX[4];
int pointY[4];
for (int i = 0; i < 4; i++)
{
pointX[i] = square[i].x;
pointY[i] = square[i].y;
}
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3 - i; j++)
{
if (pointX[j] > pointX[j + 1])
{
int tx = pointX[j];
pointX[j] = pointX[j + 1];
pointX[j + 1] = tx;
}
if (pointY[j] > pointY[j + 1])
{
int ty = pointY[j];
pointY[j] = pointY[j + 1];
pointY[j + 1] = ty;
}
}
}
Rect rect(pointX[0], pointY[0], pointX[3] - pointX[0] + 1, pointY[3] - pointY[0] + 1);
Mat roImg(image_H, rect);
int count = 0;
for (int i = 0; i<roImg.rows; i++)
{
uchar* data = roImg.ptr<uchar>(i);
for (int j = 0; j<roImg.cols; j++)
{
if (data[j] == 0)
count += 1;
}
}
if (count>0.8*((roImg.cols*roImg.rows)/2 + (pointX[2]-pointX[1]+1)*(pointY[2]-pointY[1]+1)/2))
return true;
else
return false;
}
bool getSquarePts(const Mat image, vector<vector<Point> >& squares)
{
bool isGetSquares = false;
squares.clear(); //数组清空
Mat pyr, gray0, gray, grayImg;
Mat imageHSV, image_H;
cvtColor(image, grayImg, CV_RGB2GRAY);
cvtColor(image, imageHSV, CV_BGR2HSV); //将image转到HSV空间
image_H.create(imageHSV.size(), imageHSV.depth()); //定义与imageHSV同尺寸和深度的图像image_H
int ch1[] = { 0, 0 };
mixChannels(&imageHSV, 1, &image_H, 1, ch1, 1); //将imageHSV的H层复制到image_H
for (int i = 0; i < image_H.rows; i++)
{
uchar* data = image_H.ptr<uchar>(i);
for (int j = 0; j < image_H.cols; j++)
{
if (data[j] >= 10 && data[j] <= 40)
data[j] = 0;
else
data[j] = 255;
}
}
pyrDown(grayImg, pyr, Size(image.cols / 2, image.rows / 2));
pyrUp(pyr, gray0, image.size());
Canny(gray0, gray, 0, 50, 3);
dilate(gray, gray, Mat(), Point(-1, -1));
for (int i = 0; i < gray.rows; i++)
{
uchar* data1 = gray.ptr<uchar>(i);
uchar* data2 = image_H.ptr<uchar>(i);
for (int j = 0; j < gray.cols; j++)
{
if (data1[j] == 255)
data2[j] = 255;
}
}
vector<vector<Point> > contours;
findContours(image_H, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); //对image_H进行处理,将检测出的每个轮廓(相互独立)以点集(拐点)的形式存储到contours中
vector<Point> approx; //存储矩形4个顶点的坐标的数组
for (size_t i = 0; i < contours.size(); i++)
{
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);//输出封闭的多边形顶点点集
//判断是否为四边形等条件
if (approx.size() == 4 && fabs(contourArea(Mat(approx))) > 1000 && isContourConvex(Mat(approx)))
{
double maxCosine = 0;
for (int j = 2; j < 5; j++)
{
double cosine = fabs(getAngle(approx[j % 4], approx[j - 2], approx[j - 1])); //计算夹角余弦值
maxCosine = MAX(maxCosine, cosine);
}
//如果三个夹角余弦值都小于0.3则说明是矩形,并存储矩形
if (maxCosine < 0.3&&isYellowSquare(image_H, approx))
{
squares.push_back(approx);
isGetSquares = true;
}
}
}
/*if (squares.size()>1)
{
vector<Point>center;
vector<int>item;
int d;
for (int i = 0; i<squares.size(); i++)
{
Point point;
point.x = (squares[i][0].x + squares[i][2].x) / 2;
point.y = (squares[i][0].y + squares[i][2].y) / 2;
center.push_back(point);
}
for (int i = 0; i<center.size() - 1; i++)
{
for (int j = i + 1; j<center.size(); j++)
{
d = (center[i].x - center[j].x)*(center[i].x - center[j].x) + (center[i].y - center[j].y)*(center[i].y - center[j].y);
if (d<100)
{
item.push_back(i);
break;
}
}
}
int n = 0;
for (int j = 0; j<item.size(); j++)
{
squares.erase(squares.begin() + item[j]-n);
++n;
}
}*/
return isGetSquares;
}
//旋转图像中点的函数
Point getPointAffinedPos(Point src, Point center, double angle,double scale)
{
Point dst;
int x = src.x - center.x;
int y = src.y - center.y;
dst.x = cvRound(x * cos(angle) + y * sin(angle) + center.x);
dst.y = cvRound(-x * sin(angle) + y * cos(angle) + center.y);
dst.x = (dst.x - center.x)*scale + center.x;
dst.y = (dst.y - center.y)*scale + center.y;
return dst;
}
//裁切
void cutImg(const Mat image, vector<vector<Point> > squares, vector<Mat>& rectResult)
{
for (int i_ = 0; i_ < squares.size(); i_++)
{
vector<Point>longside; //存储矩形长边的两个顶点
longside.push_back(squares[i_][1]);
longside.push_back(squares[i_][2]);
Mat rot(2, 3, CV_32FC1); //旋转矩阵
Mat rotMat = Mat::zeros(image.size(), image.type()); //定义旋转后的矩阵
Point center = Point(rotMat.cols / 2, rotMat.rows / 2); //旋转中心
double angle = atan((longside[0].y - longside[1].y) / ((longside[0].x - longside[1].x) + 0.00000001)) * 180 / CV_PI; //旋转角度
double scale = image.rows / sqrt(image.cols*image.cols + image.rows*image.rows); //缩放参数
rot = getRotationMatrix2D(center, angle, scale); //获得旋转矩阵
warpAffine(image, rotMat, rot, image.size()); //旋转并缩放图像
vector<Point>resultPoint; //存储旋转后矩形的4个顶点
Point point;
for (int i = 0; i < 4; i++)
{
point = getPointAffinedPos(squares[i_][i], Point(image.cols / 2, image.rows / 2), angle*CV_PI / 180, scale);
resultPoint.push_back(point); //存储顶点
}
//获得矩形的bounding box(近似于矩形本身)
int maxX, minX, maxY, minY;
maxX = maxY = 0;
minX = resultPoint[0].x; minY = resultPoint[0].y;
for (int i = 0; i < resultPoint.size(); i++)
{
maxX = resultPoint[i].x > maxX ? resultPoint[i].x : maxX;
minX = resultPoint[i].x < minX ? resultPoint[i].x : minX;
maxY = resultPoint[i].y > maxY ? resultPoint[i].y : maxY;
minY = resultPoint[i].y < minY ? resultPoint[i].y : minY;
}
//裁剪矩形并存储到新图像中
Rect rect(minX, minY, maxX - minX + 1, maxY - minY + 1);
Mat temp(rotMat, rect);
/*Mat temp_hsv;
cvtColor(temp, temp_hsv, COLOR_BGR2HSV);
Mat temp_H;
temp_H.create(temp_hsv.size(), temp_hsv.depth());
int ch1[] = { 0, 0 };
mixChannels(&temp_hsv, 1, &temp_H, 1, ch1, 1);
Mat Image(temp_H.size(), CV_8U);
for (int i = 0; i<Image.rows; i++)
{
uchar* data = Image.ptr<uchar>(i);
uchar* data1 = temp_H.ptr<uchar>(i);
for (int j = 0; j<Image.cols; j++)
{
if (data1[j]>32)
data[j] = 0;
else
data[j] = 255;
}
}*/
rectResult.push_back(temp);
}
cout << rectResult.size() << endl;
}
// the function draws all the squares in the image
void drawSquares(Mat& image, const vector<vector<Point> > squares)
{
int maxX, minX, maxY, minY;
for (int i = 0; i < squares.size(); i++)
{
maxX = maxY = 0;
minX = squares[i][0].x; minY = squares[i][0].y;
for (int j = 0; j < 4; j++)
{
maxX = maxX > squares[i][j].x ? maxX : squares[i][j].x;
minX = minX < squares[i][j].x ? minX : squares[i][j].x;
maxY = maxY > squares[i][j].y ? maxY : squares[i][j].y;
minY = minY < squares[i][j].y ? minY : squares[i][j].y;
}
Point point1, point2;
point1.x = minX; point1.y = minY;
point2.x = maxX; point2.y = maxY;
rectangle(image, point1, point2, (0, 0, 255), 2, 8, 0); //画矩形
}
}
bool findSquares(Mat& image, vector<Mat>& resultImage,vector<Point>& center)
{
bool isFindSquares = false;
vector<vector<Point> > squarePts;
isFindSquares = getSquarePts(image, squarePts);
if (isFindSquares)
cutImg(image, squarePts, resultImage);
else
cout << "can't find squares!" << endl;
drawSquares(image, squarePts);
for (int i = 0; i < squarePts.size(); i++)
{
Point point;
point.x = (squarePts[i][0].x + squarePts[i][2].x) / 2;
point.y = (squarePts[i][0].y + squarePts[i][2].y) / 2;
center.push_back(point);
}
waitKey(20);
return isFindSquares;
int main()
{
VideoCapture capture(0);
Mat image;
if (!capture.isOpened())
{
cout << "can not open";
cin.get();
return 0;
}
vector<vector<Point>>squares;
vector<Mat>cutImage;
while (true)
{
capture >> image;
getSquarePts(image, squares);
cutImg(image, squares, cutImage);
drawSquares(image, squares);
imshow("检测结果", image);
waitKey(30);
}
return 0;
}
}