1. 预处理
1.1 双边滤波
img.SmoothBilatral(int val1,int val2,int,val3)
(原图)
(双边滤波)
(高斯滤波)
高斯滤波将整张图都变得模糊了,双边滤波则保留了清晰轮廓特征,效果比较好。
1.2 灰度并二值
img.Convert<Gray, byte>()//灰度化g
(灰度图)
ThresholdBinary(new Gray(Parameters.BinVal),new Gray(255));//二值化
(二值图)
2. 指针提取
1.1 帧差法提取指针
用当前帧减去上一帧得到运动的指针图像。
private Image<Gray,byte> SubBackground(Image<Gray,byte>pic)
{
Image<Gray, byte> gray = new Image<Gray, byte>(pic.Size);
if (tag == 0)
{
Subbg[0] = pic;//背景帧(上一帧)
tag = 1;
return Subbg[0];
}
else
{
Subbg[1] = pic;
gray = Subbg[1] - Subbg[0];//当前帧减去背景帧(上一帧)
Subbg[0] = Subbg[1];
}
return gray;
}
(指针)
2.2 霍夫圆检测
对灰度图进行霍夫圆检测。
private Image<Bgr, byte> CirclePic(Image<Gray, byte> pic)
{
Image<Bgr, byte> outpic = new Image<Bgr, byte>(pic.Size);
//霍夫圆检测
CircleF[] circle = CvInvoke.HoughCircles(pic, Emgu.CV.CvEnum.HoughType.Gradient, 10, 1000);
foreach (CircleF c in circle)
{
CvInvoke.Circle(outpic, new Point((int)c.Center.X, (int)c.Center.Y), (int)c.Radius, new MCvScalar(255, 255, 0), 5);
center.X = (int)c.Center.X;
center.Y = (int)c.Center.Y;
radius = c.Radius;
outpic.Draw(new CircleF(new PointF(center.X, center.Y), 5), new Bgr(255, 0, 255), 10);
outpic.Draw(new LineSegment2D(new Point(0, center.Y), new Point(pic.Width, center.Y)), new Bgr(Color.Blue), 2);
outpic.Draw(new LineSegment2D(new Point(center.X, 0), new Point(center.X, pic.Height)), new Bgr(Color.Blue), 2);
outpic.Draw(new Point(center.X, center.Y).ToString(), new Point(center.X,center.Y), Emgu.CV.CvEnum.FontFace.HersheyComplexSmall, 1, new Bgr(255, 0, 255));
}
return outpic;
}
2.3 直线检测
对帧差法提取到的指针图像进行直线检测。
检测到的结果包含多条直线,首先对长度不符合的进行过滤(这里排除长度小于70的线段),过滤后仍然包含多条线段,但是我们只需要一条,所以进行直线合并,只保留一条。
//返回直线端点的坐标
public Point AvrPoint(Point[] point)
{
Point outpoint = new Point(0, 0);
int p_x = 0;
int p_y = 0;
int n = 0;
foreach (Point p in point)
{
if (p.X != 0 && p.Y != 0)
{
p_x += p.X;
p_y += p.Y;
n++;
}
}
if (n != 0)
{
p_x = p_x / n;
p_y = p_y / n;
}
outpoint = new Point(p_x, p_y);
return outpoint;
}
2.4 绘制指针
以圆心为指针的
一端,2.3中求得的线段端点为另一端绘制直线。并在同一张图片上绘制出圆心和圆(刻度盘)