目录
1、凸包检测
2、直线检测
3、点集拟合
4、二维码检测
#include
#include
using namespace cv;
using namespace std;
//凸包检测
int test1()
{
Mat img = imread("E:/testMap/hand.png");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
// 二值化
Mat gray, binary;
cvtColor(img, gray, COLOR_BGR2GRAY);
threshold(gray, binary, 105, 255, THRESH_BINARY);//105 阈值 255 maxValue
//开运算消除细小区域
Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));//获取结构元素 MORPH_RECT 获取矩形卷积核
morphologyEx(binary, binary, MORPH_OPEN, k);//MORPH_OPEN 开运算
imshow("binary", binary);
//1、轮廓发现
vector> contours;//检测到的轮廓,每个轮廓里存放像素坐标
vector hierarchy;
findContours(binary, contours, hierarchy, 0, 2, Point());//轮廓检测
for (int n = 0; n < contours.size(); n++)//此处其实只存了一个轮廓
{
//2、计算凸包
vector hull;
convexHull(contours[n], hull);//凸包检测函数
//3、绘制凸包
for (int i = 0; i < hull.size(); i++)
{
//绘制凸包顶点
circle(img, hull[i], 4, Scalar(255, 0, 0), 1, 8, 0);
//连接凸包
if (i == hull.size() - 1)//最后一个顶点与第一个顶点联接
{
line(img, hull[i], hull[0], Scalar(0, 0, 255), 1, 8, 0);
break;
}
line(img, hull[i], hull[i + 1], Scalar(0, 0, 255), 1, 8, 0);
}
}
imshow("hull", img);
waitKey(0);
return 0;
}
int main()
{
test1();
system("pause");
return 0;
}
#include
#include
using namespace cv;
using namespace std;
//直线检测
//要标记直线的图像 检测的直线数据 原图像的行数(高) 原图像的列数(宽) 绘制直线的颜色 绘制直线的线宽
void drawLine(Mat &img, vector lines,double rows,double cols,Scalar scalar,int n)
{
Point pt1, pt2;
for (size_t i = 0; i < lines.size(); i++)
{
float rho = lines[i][0]; //直线距离坐标原点的距离
float theta = lines[i][1];//直线过坐标原点垂线与x轴夹角
double a = cos(theta); //夹角的余弦值
double b = sin(theta);//夹角的正弦值
double x0 = a*rho;
double y0 = b*rho;//直线与过坐标原点的垂线的交点
double length = max(rows, cols);//图像高宽的最大值
pt1.x = cvRound(x0 + length*(-b));//计算直线上的一点
pt1.y = cvRound(y0 + length*(a));
pt2.x = cvRound(x0 - length * (-b));//计算直线上另一点
pt2.y = cvRound(y0 - length * (a));
line(img, pt1, pt2, scalar, n);//两点绘制一条直线
}
}
int test2()
{
Mat img = imread("E:/testMap/qie.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat edge;
//检测边缘图像,并二值化
Canny(img, edge, 80, 180, 3, false);
threshold(edge, edge, 170, 255, THRESH_BINARY);
//用不同的累加器进行检测直线
vector lines1, lines2;
HoughLines(edge, lines1, 1, CV_PI / 180, 50, 0, 0);
HoughLines(edge, lines2, 1, CV_PI / 180, 150, 0, 0);
//在原图像中绘制直线
Mat img1, img2;
img.copyTo(img1);
img.copyTo(img2);
drawLine(img1, lines1, edge.rows, edge.cols, Scalar(100), 2);
drawLine(img2, lines2, edge.rows, edge.cols, Scalar(200), 2);
//显示图像
imshow("img ", img);
waitKey(0);
imshow("edge", edge);
waitKey(0);
imshow("img1", img1);
waitKey(0);
imshow("img2", img2);
waitKey(0);
return 0;
}
int main()
{
test2();
system("pause");
return 0;
}
#include
#include
using namespace cv;
using namespace std;
//直线检测
//渐进概率式霍夫变换
int test2()
{
Mat img = imread("E:/testMap/qie.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat edge;
//检测边缘图像,并二值化
Canny(img, edge, 80, 180, 3, false);
threshold(edge, edge, 170, 255, THRESH_BINARY);
//利用渐进概率式霍夫变换提取直线
vector linesP1, linesP2;//Vec4i 存放两个点
HoughLinesP(edge, linesP1, 1, CV_PI / 180, 150, 30, 10);//两个点连接最大距离10
HoughLinesP(edge, linesP2, 1, CV_PI / 180, 150, 30, 30);//两个点连接最大距离30
//绘制两个点连接最大距离10直线检测结果
Mat img1;
img.copyTo(img1);
for (size_t i = 0; i < linesP1.size(); i++)
{
line(img1, Point(linesP1[i][0], linesP1[i][1]), Point(linesP1[i][2], linesP1[i][3]), Scalar(255), 3);
}
//绘制两个点连接最大距离30直线检测结果
Mat img2;
img.copyTo(img2);
for (size_t i = 0; i < linesP2.size(); i++)
{
line(img2, Point(linesP2[i][0], linesP2[i][1]), Point(linesP2[i][2], linesP2[i][3]), Scalar(255), 3);
}
//显示图像
imshow("img1", img1);
waitKey(0);
imshow("img2", img2);
waitKey(0);
return 0;
}
int main()
{
test2();
system("pause");
return 0;
}
#include
#include
using namespace cv;
using namespace std;
//点集拟合
int test3()
{
system("color 02");//更改输出界面颜色
Vec4f lines;//存放拟合后的直线
vector point;//待检测是否存在直线的所有点
const static float Points[20][2] = {
{ 0.0f, 0.0f }, { 10.0f, 11.0f }, { 21.0f, 20.0f }, { 30.0f, 30.0f },
{ 40.0f, 42.0f }, { 50.0f, 50.0f }, { 60.0f, 60.0f }, { 70.0f, 70.0f },
{ 80.0f, 80.0f }, { 90.0f, 92.0f }, { 100.0f, 100.0f }, { 110.0f, 110.0f },
{ 120.0f, 120.0f }, { 136.0f, 130.0f }, { 138.0f, 140.0f }, { 150.0f, 150.0f },
{ 160.0f, 163.0f }, { 175.0f, 170.0f }, { 181.0f, 180.0f }, { 200.0f, 190.0f } };
//将所有点存放在vector中,用于输入函数中
for (int i = 0; i < 20; i++)
{
point.push_back(Point2f(Points[i][0], Points[i][1]));
}
//参数设置
double param = 0;//距离模型中的数值参数C
double reps = 0.01;//坐标原点与直线之间的距离精度
double aeps = 0.01;//角度精度
fitLine(point, lines, DIST_L1, 0, 0.01, 0.01);//拟合直线
double k = lines[1] / lines[0];//直线斜率y/x
cout << "直线斜率: " << k << endl;
cout << "直线上一点坐标x: " << lines[2] << ", y:" << lines[3] << endl;
cout << "直线解析式: y = " << k << "(x - " << lines[2] << ") + " << lines[3] << endl;
waitKey(0);
Mat img(500, 500, CV_8UC3, Scalar::all(0));
RNG &rng = theRNG();//生成随机点
while (true)
{
int i, count = rng.uniform(1, 101);
vector points;//存放随机点集
//生成随机点
for (i = 0; i < count; i++)
{
Point pt;
pt.x = rng.uniform(img.cols / 4, img.cols * 3 / 4);
pt.y = rng.uniform(img.rows / 4, img.rows * 3 / 4);
points.push_back(pt);
}
//寻找包围点集的三角形
vector triangle;
double area = minEnclosingTriangle(points, triangle);
//寻找包围点集的圆形
Point2f center;//存放拟合圆的圆心
float radius = 0;//存放拟合圆的半径
minEnclosingCircle(points, center, radius);
//创建两个图片用于输出结果
img = Scalar::all(0);//刷新图像
Mat img2;
img.copyTo(img2);
//在图像中绘制坐标点
for (i = 0; i < count; i++)
{
circle(img, points[i], 3, Scalar(255, 255, 255), FILLED, LINE_AA);
circle(img2, points[i], 3, Scalar(255, 255, 255), FILLED, LINE_AA);
}
//绘制三角形
for (i = 0; i < 3; i++)
{
if (i == 2)
{
line(img, triangle[i], triangle[0], Scalar(255, 255, 255), 1, 16);
break;
}
line(img, triangle[i], triangle[i + 1], Scalar(255, 255, 255), 1, 16);
}
//绘制圆形
circle(img2, center, cvRound(radius), Scalar(255, 255, 255), 1, LINE_AA);
//输出结果
imshow("triangle", img);
imshow("circle", img2);
//按q键或者ESC键退出程序
char key = (char)waitKey();
if (key == 27 || key == 'q' || key == 'Q')
{
break;
}
}
return 0;
}
int main()
{
test3();
system("pause");
return 0;
}
#include
#include
using namespace cv;
using namespace std;
//二维码检测
int test4()
{
Mat img = imread("E:/testMap/erweima.jpg");
if (img.empty())
{
cout << "请确认图像文件名称是否正确" << endl;
return -1;
}
Mat gray, qrcode_bin;//qrcode_bin 存放经过矫正和二值化的QR二维码
cvtColor(img, gray, COLOR_BGR2GRAY);
QRCodeDetector qrcodedetector;//用于检测和识别二维码的类
vector points;//存放解码出的包含二维码的最小四边形的四个顶点坐标
string information;
bool isQRcode;
isQRcode = qrcodedetector.detect(gray, points);//识别二维码
if (isQRcode)
{
information = qrcodedetector.decode(gray, points, qrcode_bin);//解码二维码
cout << points << endl;//输出二维码四个顶点的坐标
}
else
{
cout << "无法识别二维码,请确认图像时候含有二维码" << endl;
return -1;
}
//绘制二维码的边框
for (int i = 0; i < points.size(); i++)
{
if (i == points.size() - 1)
{
line(img, points[i], points[0], Scalar(0, 0, 255), 2, 8);
break;
}
line(img, points[i], points[i + 1], Scalar(0, 0, 255), 2, 8);
}
//将解码内容输出到图片上
// 显示内容左上角坐标 字体类型 大小 颜色 粗细
putText(img, information.c_str(), Point(5, 10), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 100, 255), 0.5, 8);
//利用函数直接定位二维码并解码
string information2;
vector points2;
information2 = qrcodedetector.detectAndDecode(gray, points2);
cout << points2 << endl;
putText(img, information2.c_str(), Point(5, 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 100, 0), 0.5, 8);
//输出结果
namedWindow("result", WINDOW_NORMAL);
imshow("result", img);
namedWindow("qrcode_bin", WINDOW_NORMAL);
imshow("qrcode_bin", qrcode_bin);
waitKey(0);
return 0;
}
int main()
{
test4();
system("pause");
return 0;
}