【blog算法原理】Opencv中直线的表示方法
一、问题的提出:
在实际项目编写过程中,需要对直线(Line)进行特定的处理。在以前的项目设计实现中,直线(Line)多是用来绘图使用的,而不是用来进行分析的。
经过较为仔细地研究Opencv提供的相关内容,感觉这个问题很有搞头,所以分离出来研究。先看refman
可以看到,opencv自己提供的3种直线寻找的函数,最后得到的表示line的数据结构和表示内容的表示都是不一样的。出现这个原因,可能是因为编写这几个函数的不是一个开发者;也可能是认为地选择了最适合特定函数使用的数据结构。那么这3个函数效果到底怎么样?如何灵活使用到自己的项目中?最后我将提出结合自己实际编写的函数。
二、函数测试
由于后2个函数都能够直接以图像(MAT)作为参数,所以用一副标准图像进行测试;而后针对Linefit能够以点集作为输入的情况单独测试(如果要使用同样的图像需要先细化再找边缘,比较麻烦),并且提出自己编写的方法。
测试图像为
编写代码
#
include
"stdafx.h"
#
include
<iostream
>
#
include
"opencv2/core/core.hpp"
#
include
"opencv2/highgui/highgui.hpp"
#
include
"opencv2/imgproc/imgproc.hpp"
//【blog算法原理】Opencv中直线的表示方法
// jsxyhelu 2016年1月20日
using
namespace std;
using
namespace cv;
void main()
{
Mat src;
Mat board;
//用于将识别出来直线绘制出来
Mat board2;
vector
<Vec4i
> lines;
vector
<Vec2f
> linesf;
///////////////////////主要流程///////////////////////////////////////
src
= imread(
"PureLine.jpg",
0);
board
= Mat
:
:zeros(src.size(),src.type());
board2
= Mat
:
:zeros(src.size(),src.type());
////HoughLineP测试
HoughLinesP(src, lines,
1, CV_PI
/
180,
50,
50,
10 );
////HoughLine测试
HoughLines(src, linesf,
1, CV_PI
/
180,
100,
0,
0 );
///////////////////////显示结果///////////////////////////////////////
for( size_t i
=
0; i
< lines.size(); i
++ ){
Vec4i l
= lines[i];
line( board, Point(l[
0], l[
1]), Point(l[
2], l[
3]), Scalar(
255),
1, CV_AA);
}
for( size_t i
=
0; i
< linesf.size(); i
++ ){
float rho
= linesf[i][
0], theta
= lines[i][
1];
Point pt1, pt2;
double a
= cos(theta), b
= sin(theta);
double x0
= a
*rho, y0
= b
*rho;
pt1.x
= cvRound(x0
+
1000
*(
-b));
pt1.y
= cvRound(y0
+
1000
*(a));
pt2.x
= cvRound(x0
-
1000
*(
-b));
pt2.y
= cvRound(y0
-
1000
*(a));
line( board2, pt1, pt2, Scalar(
255),
1, CV_AA);
}
imshow(
"src",src);
waitKey();
}
结果
(HoughLineP)
(HoughLine)
从结果上来看,HoughlineP识别的要更准确。这两个函数一个是识别出来图形上的点,一个是识别出来角度和图像上的点。两个函数的结果都是自己编写代码打印出来的。
三、结合实际
实际上我需要的是识别出直线,并且对图像进行旋转。这部分的代码是这样的
Point pt1;
Point pt2;
float t
= (
float)(src.cols
+src.rows);
pt1.x
= cvRound(Line1[
2]
- Line1[
0]
*t);
pt1.y
=cvRound(Line1[
3]
-Line1[
1]
*t);
pt2.x
= cvRound(Line1[
2]
+Line1[
0]
*t);
pt2.y
= cvRound(Line1[
3]
+Line1[
1]
*t);
line( src, pt1, pt2, Scalar(
255),
1, CV_AA);
//对结果图像进行旋转
Point center
= Point( src.cols
/
2, src.rows
/
2 );
//以图像中心为中心
double angle
=atan(Line1[
1]
/Line1[
0]);
angle
= Rad2Deg(angle);
//由弧度转换为角度
/// 通过上面的旋转细节信息求得旋转矩阵
Mat rot_mat
= getRotationMatrix2D( center, angle,
1 );
/// 旋转已扭曲图像
warpAffine( src, dst, rot_mat, src.size() );
目前方向:图像拼接融合、图像识别 联系方式:jsxyhelu@foxmail.com