#include<opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat one,one1,two,cannySrc;
one=imread("/home/zengdegang/图片/颜色识别图片/1558a1b11016dd9ea9ad087c03389c8.jpg");
//图像预处理
cvtColor(one,two,COLOR_BGR2GRAY);
GaussianBlur(two,two,Size(3,3),10,10);
//threshold(two,two,180, 230, 4);
Canny(two,cannySrc,200,95); //阈值1和阈值2比例推荐用2:1或者3:1
//提取轮廓
vector<vector<Point>> contours; //储存轮廓
vector<Vec4i> hierarchy;
findContours(cannySrc, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); //获取轮廓
for (int index = 0; index < contours.size(); index++)
{
drawContours(cannySrc, contours, index, Scalar(255,0,255), 2, 8);
}
vector<vector<Point>> polyContours(contours.size());
int maxArea = 0;
for (int index = 0; index < contours.size(); index++){
if (contourArea(contours[index]) > contourArea(contours[maxArea]))
maxArea = index;
approxPolyDP(contours[index], polyContours[index], 10, true);
}
//画出矩形,同样注意要提前为Mat分配空间
Mat polyPic = Mat::zeros(cannySrc.size(), CV_8UC3);
drawContours(polyPic, polyContours, maxArea, Scalar(255,255,255), 2);
//寻找凸包
vector<int> hull;
convexHull(polyContours[maxArea], hull, false); //检测该轮廓的凸包
//将点和多边形加到原图查看效果
for (int i = 0; i < hull.size(); ++i)
{
circle(polyPic, polyContours[maxArea][i], 10, Scalar(rand() & 255, rand() & 255, rand() & 255), 3);
}
addWeighted(polyPic, 0.5, one, 0.5, 0, one);
//dstPoints储存的是变换后各点的坐标,依次为左上,右上,右下, 左下
//srcPoints储存的是上面得到的四个角的坐标
Point2f srcPoints[4], dstPoints[4];
dstPoints[0] = Point2f(0, 0);
dstPoints[1] = Point2f(one.cols, 0);
dstPoints[2] = Point2f(one.cols, one.rows);
dstPoints[3] = Point2f(0, one.rows);
//对得到的4个点进行处理
// for (int i = 0; i < 4; i++)
// { //恢复坐标到原图
// polyContours[maxArea][i] = Point2f(polyContours[maxArea][i].x * 4, polyContours[maxArea][i].y * 4);
// }
//对四个点进行排序 分出左上 右上 右下 左下
bool sorted = false;
int n = 4;
while (!sorted)
{
for (int i = 1; i < n; i++){
sorted = true;
if (polyContours[maxArea][i-1].x > polyContours[maxArea][i].x)
{
swap(polyContours[maxArea][i-1], polyContours[maxArea][i]);
sorted = false;
}
}
n--;
}
if (polyContours[maxArea][0].y < polyContours[maxArea][1].y)
{
srcPoints[0] = polyContours[maxArea][0];
srcPoints[3] = polyContours[maxArea][1];
}
else
{
srcPoints[0] = polyContours[maxArea][1];
srcPoints[3] = polyContours[maxArea][0];
}
if (polyContours[maxArea][2].y < polyContours[maxArea][3].y)
{
srcPoints[1] = polyContours[maxArea][2];
srcPoints[2] = polyContours[maxArea][3];
}
else
{
srcPoints[1] = polyContours[maxArea][3];
srcPoints[2] = polyContours[maxArea][2];
}
Mat transMat = getPerspectiveTransform(srcPoints, dstPoints); //得到变换矩阵
warpPerspective(one, one1, transMat, one.size()); //进行坐标变换
imshow(" ",one1 );
waitKey(0);
return 0;
}
改进版
用inrange来替代canny,将图中黑色区域给消掉,剩下的灰色就是最大的轮廓
原图:

效果图:

代码如下:
#include<opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
Mat one,one1,two,cannySrc;
one=imread("/home/zdg/图片/颜色识别图片/7.jpg");
//图像预处理
cvtColor(one,two,COLOR_BGR2HSV);
GaussianBlur(two,two,Size(3,3),15,15);
inRange(two,Scalar(0,0,100),Scalar(180,255,255),cannySrc);
imshow("ww",cannySrc);
//提取轮廓
vector<vector<Point>> contours; //储存轮廓
vector<Vec4i> hierarchy;
findContours(cannySrc, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE); //获取轮廓
for (int index = 0; index < contours.size(); index++)
{
drawContours(cannySrc, contours, index, Scalar(255,0,255), 2, 8);
}
vector<vector<Point>> polyContours(contours.size());
int maxArea = 0;
for (int index = 0; index < contours.size(); index++){
if (contourArea(contours[index]) > contourArea(contours[maxArea]))
maxArea = index;
approxPolyDP(contours[index], polyContours[index], 10, true);
}
//画出矩形,同样注意要提前为Mat分配空间
Mat polyPic = Mat::zeros(cannySrc.size(), CV_8UC3);
drawContours(polyPic, polyContours, maxArea, Scalar(255,255,255), 2);
//寻找凸包
vector<int> hull;
convexHull(polyContours[maxArea], hull, false); //检测该轮廓的凸包
//dstPoints储存的是变换后各点的坐标,依次为左上,右上,右下, 左下
//srcPoints储存的是上面得到的四个角的坐标
Point2f srcPoints[4], dstPoints[4];
dstPoints[0] = Point2f(0, 0);
dstPoints[1] = Point2f(one.cols, 0);
dstPoints[2] = Point2f(one.cols, one.rows);
dstPoints[3] = Point2f(0, one.rows);
//对四个点进行排序 分出左上 右上 右下 左下
bool sorted = false;
int n = 4;
while (!sorted)
{
for (int i = 1; i < n; i++){
sorted = true;
if (polyContours[maxArea][i-1].x > polyContours[maxArea][i].x)
{
swap(polyContours[maxArea][i-1], polyContours[maxArea][i]);
sorted = false;
}
}
n--;
}
if (polyContours[maxArea][0].y < polyContours[maxArea][1].y)
{
srcPoints[0] = polyContours[maxArea][0];
srcPoints[3] = polyContours[maxArea][1];
}
else
{
srcPoints[0] = polyContours[maxArea][1];
srcPoints[3] = polyContours[maxArea][0];
}
if (polyContours[maxArea][2].y < polyContours[maxArea][3].y)
{
srcPoints[1] = polyContours[maxArea][2];
srcPoints[2] = polyContours[maxArea][3];
}
else
{
srcPoints[1] = polyContours[maxArea][3];
srcPoints[2] = polyContours[maxArea][2];
}
Mat transMat = getPerspectiveTransform(srcPoints, dstPoints); //得到变换矩阵
warpPerspective(one, one1, transMat, one.size()); //进行坐标变换
imshow(" ",one1);
waitKey(0);
return 0;
}
436

被折叠的 条评论
为什么被折叠?



