本示例是《OpenCV3编程入门》中7.2.4的示例程序的C# + EMGU 3.4.1版,关于C# EMGU中的霍夫变换,有如下几点需要注意:
1. HoughLines函数检测出来的不是线段,而是(ρ,θ)对,在C++ OpenCv中,使用std::vector<Vec2f> lines来存放,而在C# EMGU中,则用EMGU.CV.Util.VectorOfPointF lines来存放;
2. 由于上述原因,画线的时候需要自己先选一个y(最小为0),求一个x,得到一个点;然后再选一个y(选为图像的高度),再求x,得到另一个点,这样画出的线能够贯穿整个图像。
程序代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Util; //用于定义vector的cv命名空间
using Emgu.CV.Structure;
namespace HoughLines
{
class Program
{
static void Main(string[] args)
{
//载入原始图
Mat srcImage = CvInvoke.Imread("Building2.jpg");
//临时变量和目标图的定义
Mat tempImage = new Mat(), dstImage = new Mat();
//进行Canny边缘检测
CvInvoke.Canny(srcImage, tempImage, 80, 240);
//灰度转换,此处dstImage之所以要转换成color形式,是为了后面绘制line时,可以使用彩色line
CvInvoke.CvtColor(tempImage, dstImage, ColorConversion.Gray2Bgr);
//进行霍夫线变换
VectorOfPointF lines = new VectorOfPointF(); //定义一个矢量结构lines,等价于opencv中的vector<Vec2f>
CvInvoke.HoughLines(tempImage, lines, 1, Math.PI / 180, 250, 0, 0);
//依次在图中绘制出每条线段
for (int i = 0; i < lines.Size; i++)
{
PointF p = lines[i];
float rho = p.X; //原点到直线的距离
float theta = p.Y; //直线的角度
double a = Math.Cos(theta), b = Math.Sin(theta);
double x0 = rho * a, y0 = rho * b;
Point pt1 = new Point(), pt2 = new Point();
pt1.X = (int)Math.Round(x0 - 1000 * b);
pt1.Y = (int)Math.Round(y0 + 1000 * a);
pt2.X = (int)Math.Round(x0 + 1000 * b);
pt2.Y = (int)Math.Round(y0 - 1000 * a);
CvInvoke.Line(dstImage, pt1, pt2, new MCvScalar(55, 100, 195), 1, LineType.AntiAlias); //LineType.AntiAlias表示抗锯齿
}
CvInvoke.Imshow("SourceImage", srcImage); //显示原始图
CvInvoke.Imshow("CannyImage", tempImage); //显示Canny边缘检测后的图
CvInvoke.Imshow("HoughTransformImage", dstImage); //显示霍夫变换后的效果图
CvInvoke.WaitKey(0);
}
}
}
完整的程序资源可到以下链接下载:
https://download.csdn.net/download/flymoon87/10684074
程序运行结果如下:
原始图:
Cnnay边缘检测后的图:
霍夫变换后的图: