最终效果如下:

左侧为检测图片、右侧为模板,右下角textbox为轮毂中心的像素坐标

操作步骤:

1、点击打开图像选择一张比较不错的图片,用于画模板;

2、在picturebox中画取ROI区域生成模板(拖拽线不显示就合理利用微软提供的画形状的方法和合理使用picturebox.Refresh()即可解决);

3、重新选取一张待检测图片,点击模板匹配,即可找到ROI区域并把圆的边界和圆心找到;

完整代码如下(代码还有待改善):

using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Linq;
using System.Windows.Forms;
using Point = OpenCvSharp.Point;
using Size = OpenCvSharp.Size;namespace DrawROI
{public partial class Form1 : Form{private System.Drawing.Point RectStartPoint, tempEndPoint;bool blnDraw;Mat ImageROI;Mat OrgMat;private string FilePath;public Form1(){InitializeComponent();}private void pictureBox1_MouseDown(object sender, MouseEventArgs e){RectStartPoint = e.Location; //获得鼠标按下的pictureBox上坐标Invalidate();blnDraw = true;//判断标志}private void pictureBox1_MouseMove(object sender, MouseEventArgs e){if (blnDraw){if (e.Button != MouseButtons.Left)//判断是否按下左键{return;}tempEndPoint = e.Location; //记录框的位置和大小//pictureBox上开始点坐标//Rect.Location = new System.Drawing.Point(//Math.Min(RectStartPoint.X, tempEndPoint.X),//Math.Min(RectStartPoint.Y, tempEndPoint.Y));pictureBox上矩形大小//Rect.Size = new System.Drawing.Size(//Math.Abs(RectStartPoint.X - tempEndPoint.X),//Math.Abs(RectStartPoint.Y - tempEndPoint.Y));pictureBox1.Invalidate();// 最后点位置int X0, Y0;Utilities.ConvertCoordinates(pictureBox1, out X0, out Y0, e.X, e.Y);//在控件中//textBox1.Text = Convert.ToString("pictureBox最后点坐标" + e.X + "  ," + e.Y); //pictureBox 上终点坐标//textBox2.Text = Convert.ToString("pictureBox开始点坐标" + Rect.X + "  ," + Rect.Y); //开始点坐标//textBox3.Text = Convert.ToString("pictureBox的Width" + Rect.Width + "  ," + Rect.Height);//大小//Create ROI 感兴趣区域Utilities.ConvertCoordinates(pictureBox1, out X0, out Y0, RectStartPoint.X, RectStartPoint.Y);int X1, Y1;Utilities.ConvertCoordinates(pictureBox1, out X1, out Y1, tempEndPoint.X, tempEndPoint.Y);//感兴趣区域 左上点坐标-宽-高//RealImageRect.Location = new System.Drawing.Point(//    Math.Min(X0, X1),//    Math.Min(Y0, Y1));//RealImageRect.Size = new System.Drawing.Size(//    Math.Abs(X0 - X1),//    Math.Abs(Y0 - Y1));//textBox4.Text = "原图像上最后点坐标: X:" + X0 + "  Y:" + Y0;//textBox5.Text = "原图像上RealImageRect: X:" + RealImageRect.X + "  Y:" + RealImageRect.Y; // 原图像-左上点坐标//textBox6.Text = "原图像上RealImageRectSize: X:" + RealImageRect.Width + "  Y:" + RealImageRect.Height; // 原图像-大小Rect tmp_Rect = new Rect(Math.Min(X0, X1), Math.Min(Y0, Y1), Math.Abs(X0 - X1), Math.Abs(Y0 - Y1));ImageROI = new Mat(OrgMat, tmp_Rect);//新建一个mat,把roi内的图像加载到里面去。//Cv2.ImWrite("4.jpg",ImageROI);  //保存       }}private void pictureBox1_MouseUp(object sender, MouseEventArgs e){// mouseUp 结束以后 将图像显示在pictureBox2控件中pictureBox2.Image = ImageROI.ToBitmap();//***************************************//blnDraw = false; //结束绘制      }private void button1_Click(object sender, EventArgs e){OpenFileDialog openFileDialog = new OpenFileDialog();openFileDialog.ShowDialog();FilePath = openFileDialog.FileName;OrgMat = new Mat(FilePath, ImreadModes.Grayscale);OrgMat.MedianBlur(3);pictureBox1.Image = BitmapConverter.ToBitmap(OrgMat);}private void button3_Click(object sender, EventArgs e){if (ImageROI == null){MessageBox.Show("请先绘制模板");return;}Mat RoiClone = ImageROI.Clone();Mat mat3 = new Mat();//创建result的模板,就是MatchTemplate里的第三个参数//mat3.Create(mat1.Cols - mat2.Cols + 1, mat1.Rows - mat2.Rows + 1, MatType.CV_32FC1);//进行匹配(1母图,2模版子图,3返回的result,4匹配模式)Cv2.MatchTemplate(OrgMat, RoiClone, mat3, TemplateMatchModes.SqDiff);//对结果进行归一化(这里我测试的时候没有发现有什么用,但在opencv的书里有这个操作,应该有什么神秘加成,这里也加上)Cv2.Normalize(mat3, mat3, 1, 0, NormTypes.MinMax, -1);//double minValue, maxValue;Point minLocation, maxLocation;/// 通过函数 minMaxLoc 定位最匹配的位置/// (这个方法在opencv里有5个参数,这里我写的时候发现在有3个重载,看了下可以直接写成拿到起始坐标就不取最大值和最小值了)/// minLocation和maxLocation根据匹配调用的模式取不同的点Cv2.MinMaxLoc(mat3, out minLocation, out maxLocation);Mat OrgMatClone = OrgMat.Clone();//画出匹配的矩,//Cv2.Rectangle(mask, maxLocation, new Point(maxLocation.X + mat2.Cols, maxLocation.Y + mat2.Rows), Scalar.Red, 2);Cv2.Rectangle(OrgMatClone, minLocation, new Point(minLocation.X + RoiClone.Cols, minLocation.Y + RoiClone.Rows), Scalar.Red, 2);//Cv2.ImShow("mat1", mat1);//Cv2.ImShow("mat2", mat2);//霍夫圆检测:使用霍夫变换查找灰度图像中的圆。/** 参数:*      1:输入参数: 8位、单通道、灰度输入图像*      2:实现方法:目前,唯一的实现方法是HoughCirclesMethod.Gradient*      3: dp      :累加器分辨率与图像分辨率的反比。默认=1*      4:minDist: 检测到的圆的中心之间的最小距离。(最短距离-可以分辨是两个圆的,否则认为是同心圆-                            src_gray.rows/8)*      5:param1:   第一个方法特定的参数。[默认值是100] canny边缘检测阈值低*      6:param2:   第二个方法特定于参数。[默认值是100] 中心点累加器阈值 – 候选圆心*      7:minRadius: 最小半径*      8:maxRadius: 最大半径* */CircleSegment[] cs = Cv2.HoughCircles(RoiClone, HoughMethods.Gradient, 1, 80, 70, 100, 100, 200);for (int i = 0; i < cs.Count(); i++){//画圆Cv2.Circle(OrgMatClone, (int)(cs[i].Center.X + minLocation.X), (int)(cs[i].Center.Y + minLocation.Y), (int)cs[i].Radius, new Scalar(0, 0, 255), 2, LineTypes.AntiAlias);//加强圆心显示Cv2.Circle(OrgMatClone, (int)cs[i].Center.X, (int)cs[i].Center.Y, 3, new Scalar(0, 0, 255), 2, LineTypes.AntiAlias);textBox1.Text = cs[i].Center.X.ToString();textBox2.Text = cs[i].Center.Y.ToString();}//pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;pictureBox1.Image = BitmapConverter.ToBitmap(OrgMatClone);}//private void pictureBox1_Paint(object sender, PaintEventArgs e)//{//    if (blnDraw)//    {//        if (pictureBox1.Image != null)//        {//            if (Rect != null && Rect.Width > 0 && Rect.Height > 0)//            {//                e.Graphics.DrawRectangle(new Pen(Color.Red, 1), Rect);//重新绘制颜色为红色//            }//        }//    }//}public class Utilities{//坐标转换//**************************************//* 图片左边转换,//* Input输入: pictureBox 坐标X,Y//* Output输出: Image 图像上对应的坐标//**************************************//public static void ConvertCoordinates(PictureBox pic,out int X0, out int Y0, int x, int y){int pic_hgt = pic.ClientSize.Height;int pic_wid = pic.ClientSize.Width;int img_hgt = pic.Image.Height;int img_wid = pic.Image.Width;X0 = x;Y0 = y;switch (pic.SizeMode){case PictureBoxSizeMode.AutoSize:case PictureBoxSizeMode.StretchImage:X0 = (int)(img_wid * x / (float)pic_wid);Y0 = (int)(img_hgt * y / (float)pic_hgt);break;}}}

OpenCvSharp手绘ROI区域+模板匹配+霍夫变换检测圆的边界相关推荐

  1. Python 采集87个手绘风格PPT模板

    源码下载链接:ppt.rar - 蓝奏云 PPT下载链接:https://pan.baidu.com/s/1HUAEe_-4IEV6ttOKC_VPuA?pwd=96px  提取码:96px 采集的参 ...

  2. 使用模板匹配方法检测苹果缺陷

    """ 使用模板匹配方法检测苹果缺陷 """ import cv2 import matplotlib.pyplot as plt#读取待检 ...

  3. Canny算子与霍夫变换检测圆与直线

    目录 引言 一.canny算子 二.canny算子代码 三.霍夫变换检测直线 四.霍夫变换检测直线代码 五.霍夫变换检测直线效果 六.霍夫变换检测圆 七.霍夫变换检测圆代码 八.霍夫变换检测圆效果 引 ...

  4. 霍夫变换MATLAB怎么实现,做过Matlab关于霍夫变换检测圆的高手请进

    Hough变换对圆的检测 Hough变换的基本原理在于,利用点与线的对偶性,将图像空间的线条变为参数空间的聚集点,从而检测给定图像是否存在给定性质的曲线. Hough对圆的检测程序如下  完整的程序及 ...

  5. 霍夫变换检测圆c 语言,c++ 霍夫变换检测直线

    通常这是一幅边缘图像,比如来自 Canny算子.cv:: Houghlines函数的输出是 cV::Vec2f向量,每个元素都是一对代表检测到的直线的浮点数(p,0).在下例中 我们首先应用 Cann ...

  6. Matlab findcircle函数实现 霍夫变换——检测圆

    Matlab findcircle函数实现 霍夫变换--检测圆 实现了基于霍夫变换的findcircle函数,function[circlefind]=findcircle(img,minr,maxr ...

  7. opencv霍夫变换检测圆cvHoughCircles和直线cvHoughLines2的应用

    opencv霍夫变换检测圆cvHoughCircles和直线cvHoughLines2的应用 1)cvHonghLines2:直线 2)cvHoughCircles:该函数用Hough变换在二值图像中 ...

  8. [模板匹配霍夫变换]——模板匹配分析、霍夫变换分析

    一.模板匹配分析 所谓模板匹配,就是在给定的图片中查找和模板最相似的区域,该算法的输入包括模板和图片,整个任务的思路就是按照滑窗的思路不断的移动模板图片,计算其与图像中对应区域的匹配度,最终将匹配度最 ...

  9. halcon窗体的移动和缩放_Halcon hWindowControl 鼠标缩放平移区域模板匹配绘制

    如题所示标题,想同时表达两个意思:1:缩放平移绘制区域,2:创建模板匹配区域并保存.被一个技术问题卡住折腾了近大半天时间+熬夜2个小时,经过不懈努力,反复验证各参数意义,找到了问题的原因,终于攻克难题 ...

最新文章

  1. 提高图形匹配精度,亮风台提出「完全可训练」的图匹配方法|CVPR 2020 Oral
  2. ogre研究之第一个程序(二)
  3. python编写抢座位软件_程序员硬核Python抢票教程”,帮你抢回家车票
  4. 中海达数据怎么转rinex_hds2003下载-中海达HDS2003数据处理软件下载20120530 官方版-中海达GPS数据转RINEX格式西西软件下载...
  5. 杭电4786--Fibonacci Tree(生成树)
  6. 嵌入在网页上Flash媒体播放器(1)
  7. 程序员必备算法——算法相关链接总结
  8. 字符串分割的时候用StringUtils.split()方法代替string自带的split,特殊字符不用转义
  9. VC6.0和VC2005项目配置详解
  10. 项目管理软件 OpenProj
  11. Python常用模块大全
  12. office2007无法卸载 无法安装
  13. Unity VR太空射击游戏教程
  14. 图片转svg并动态修改其颜色
  15. STM32F103ZET6如何驱动DS18B20温度传感器
  16. PHP随机生成英文大小写
  17. scribd.com文档下载
  18. geoip php 获取城市,Laravel 中利用 GeoIP 获取用户地理位置信息
  19. DRM应用程序进阶 (atomic-crtc)
  20. MySQL基础知识,如果有疏漏、错误的地方请大家指出

热门文章

  1. Quartus和Modelsim中使用`include包含头文件的对比
  2. 频谱细化(补零、zfft、czt)
  3. Matlab生成Xilinx Rom IP CORE的初始化内容coe文件
  4. jittor和pytorch生成网络对比之wgan
  5. ES6-Promise对象
  6. mongodb分享(二)
  7. MyBatis—insert语句返回主键和selectKey标签
  8. java中的equals方法
  9. linux,ssh,ftp,server
  10. pthread_create()之前的属性设置