C#使用OpenCV剪切图像中的圆形和矩形
前言
本文主要介绍如何使用OpenCV剪切图像中的圆形和矩形。
准备工作
首先创建一个Wpf项目——WpfOpenCV,这里版本使用Framework4.7.2。
然后使用Nuget搜索【Emgu.CV】,如下图。
这里的Emgu.CV选择4.3.0.3890版本,然后安装Emgu.CV和Emgu.CV.runtime.windows。
使用OPenCV剪切矩形
现在,我们进入项目,进行OPenCV的调用。
首先引入命名空间,如下:
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System.Drawing;
using System.Windows.Forms;
然后编写矩形剪切函数——CutRectangleImage。
函数里,我们先将图像进行缩放,这样可以有效的减少检测到的矩形数量。
再将图片处理成灰度模式,然后再高斯模糊,再边缘化。
然后,我们就可以在图片里查找图形轮廓了,当轮廓有三个顶点,那么它是三角形,如果有四个顶点,那么它是四边形;我们要截取矩形,所以这里要加一个角度的判断,四个角必须都在80-100度之间。
取到了顶点后,在依据顶点剪切图片就可以了。
下面是截取矩形的代码,代码中只截取了宽度最大的那个矩形。
public void CutRectangleImage(string imagePath)
{Image<Bgr, Byte> src = new Image<Bgr, byte>(imagePath);int scale = 1;if (src.Width > 500){scale = 2;}if (src.Width > 1000){scale = 10;}if (src.Width > 10000){scale = 100;}var size = new Size(src.Width / scale, src.Height / scale);Image<Bgr, Byte> srcNewSize = new Image<Bgr, byte>(size);CvInvoke.Resize(src, srcNewSize, size);//将图像转换为灰度UMat grayImage = new UMat(); CvInvoke.CvtColor(srcNewSize, grayImage, ColorConversion.Bgr2Gray);//使用高斯滤波去除噪声CvInvoke.GaussianBlur(grayImage, grayImage, new Size(3, 3), 3);UMat cannyEdges = new UMat();CvInvoke.Canny(grayImage, cannyEdges, 60, 180);//通过边缘化,然后取出轮廓#region 取三角形和矩形的顶点坐标List<Triangle2DF> triangleList = new List<Triangle2DF>();List<RotatedRect> boxList = new List<RotatedRect>(); //旋转的矩形框
using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint()){CvInvoke.FindContours(cannyEdges, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);int count = contours.Size;for (int i = 0; i < count; i++){using (VectorOfPoint contour = contours[i])using (VectorOfPoint approxContour = new VectorOfPoint()){CvInvoke.ApproxPolyDP(contour, approxContour, CvInvoke.ArcLength(contour, true) * 0.08, true);//仅考虑面积大于50的轮廓if (CvInvoke.ContourArea(approxContour, false) > 50){if (approxContour.Size == 3) //轮廓有3个顶点:三角形{System.Drawing.Point[] pts = approxContour.ToArray();triangleList.Add(new Triangle2DF(pts[0], pts[1], pts[2]));}else if (approxContour.Size == 4) //轮廓有4个顶点{#region 检测角度,如果角度都在 [80, 100] 之间,则为矩形bool isRectangle = true;System.Drawing.Point[] pts = approxContour.ToArray();LineSegment2D[] edges = Emgu.CV.PointCollection.PolyLine(pts, true);
for (int j = 0; j < edges.Length; j++){double angle = Math.Abs(edges[(j + 1) % edges.Length].GetExteriorAngleDegree(edges[j]));if (angle < 80 || angle > 100){isRectangle = false;break;}}#endregionif (isRectangle) boxList.Add(CvInvoke.MinAreaRect(approxContour));}}}}}#endregion#region 保存剪切的最大的矩形图片 Rectangle rectangle = new Rectangle(0, 0, src.Width, src.Height);int maxWidth = 0;//boxList = boxList.Where(p => p.Size.Width > 300).ToList();for (int i = 0; i < boxList.Count(); i++){RotatedRect box = boxList[i];Rectangle rectangleTemp = box.MinAreaRect();//这里对取到的顶点坐标进行了加宽,因为矩形可能存在角度,这里没有进行角度旋转,所以加宽了取值范围就可以取到完整的图了rectangleTemp = new Rectangle(rectangleTemp.X * scale, rectangleTemp.Y * scale, rectangleTemp.Width * scale + scale, rectangleTemp.Height * scale + scale);//取最大的矩形图片if (rectangleTemp.Width > maxWidth){maxWidth = rectangleTemp.Width;rectangle = rectangleTemp;}}src.Draw(rectangle, new Bgr(System.Drawing.Color.Red), 4);//在图片中画线CvInvoke.Imwrite("原始图片.bmp", src); //保存原始图片CvInvoke.cvSetImageROI(src.Ptr, rectangle);//设置兴趣点—ROI(region of interest )var clone = src.Clone(); CvInvoke.Imwrite("剪切的矩形图片.bmp", clone); //保存结果图 #endregionsrc.Dispose();srcNewSize.Dispose();grayImage.Dispose();
}
然后编写一个打开文件的函数,在成功打开文件后调用CutRectangleImage。
private void btnRectangle_Click(object sender, RoutedEventArgs e)
{System.Windows.Forms.OpenFileDialog frm = new System.Windows.Forms.OpenFileDialog();frm.Filter = "(*.jpg,*.png,*.jpeg,*.bmp,*.gif)|*.jgp;*.png;*.jpeg;*.bmp;*.gif|All files(*.*)|*.*";if (frm.ShowDialog() == System.Windows.Forms.DialogResult.OK){CutRectangleImage(frm.FileName);}
}
然后运行项目,点击剪切矩形文件。
然后到debug文件夹下,查看结果。
测试结果如下图所示:
图中红线为检测到矩形后,手动画上去的矩形轮廓。
使用OPenCV剪切圆形
编写矩形剪切函数——CutCircleImage。
函数里,我们依然先将图像进行缩放,为了有效的减少检测到的圆形数量。
再将图片处理成灰度模式,然后再高斯模糊。
然后再使用霍夫圆检测函数,获取圆的圆心和半径。
最后再根据圆心和半径计算出最小矩形,然后将圆剪切并保存。
代码如下:
public void CutCircleImage(string imagePath)
{ Image<Bgr, Byte> src = new Image<Bgr, byte>(imagePath);int scale = 1;if (src.Width > 500){scale = 2;}if (src.Width > 1000){scale = 10;}if (src.Width > 10000){scale = 100;} var size = new Size(src.Width / scale, src.Height / scale);Image<Bgr, Byte> srcNewSize = new Image<Bgr, byte>(size);CvInvoke.Resize(src, srcNewSize, size);//将图像转换为灰度UMat grayImage = new UMat();CvInvoke.CvtColor(srcNewSize, grayImage, ColorConversion.Bgr2Gray); //使用高斯滤波去除噪声CvInvoke.GaussianBlur(grayImage, grayImage, new Size(3, 3), 3); //霍夫圆检测CircleF[] circles = CvInvoke.HoughCircles(grayImage, HoughModes.Gradient, 2.0, 200.0, 100.0, 180.0, 5);Rectangle rectangle = new Rectangle();float maxRadius = 0;foreach (CircleF circle in circles){var center = circle.Center;//圆心var radius = circle.Radius;//半径if (radius > maxRadius){maxRadius = radius;rectangle = new Rectangle((int)(center.X - radius) * scale,(int)(center.Y - radius) * scale,(int)radius * 2 * scale + scale,(int)radius * 2 * scale + scale);}srcNewSize.Draw(circle, new Bgr(System.Drawing.Color.Blue), 4);
}CvInvoke.Imwrite("原始图片.bmp", srcNewSize); //保存原始图片if (maxRadius == 0){MessageBox.Show("没有圆形");}CvInvoke.cvSetImageROI(srcNewSize.Ptr, rectangle);//设置兴趣点—ROI(region of interest )var clone = srcNewSize.Clone();CvInvoke.Imwrite("剪切的圆形图片.bmp", clone); //保存结果图 src.Dispose();srcNewSize.Dispose();grayImage.Dispose();
}
运行项目进行测试,结果如下:
----------------------------------------------------------------------------------------------------
到此,C#使用OpenCV剪切图像中的圆形和矩形就已经介绍完了。
代码已经传到Github上了,欢迎大家下载。
Github地址: https://github.com/kiba518/OpenCv_CutImage
----------------------------------------------------------------------------------------------------
注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
若您觉得这篇文章还不错,请点击下方的【推荐】,非常感谢!
C#使用OpenCV剪切图像中的圆形和矩形 - kiba518 - 博客园
C#使用OpenCV剪切图像中的圆形和矩形相关推荐
- Python+opencv 机器视觉 - 基于霍夫圈变换算法检测图像中的圆形实例演示
Python+opencv 机器视觉 - 基于霍夫圈变换算法检测图像中的圆形实例演示 第一章:霍夫变换检测圆 ① 实例演示1 ② 实例演示2 ③ 霍夫变换函数解析 第二章:Python + openc ...
- 使用Python和OpenCV检测图像中的条形码
使用Python和OpenCV检测图像中的条形码 1. 效果图 2. 算法的步骤 3. 源码 参考 这篇博客将介绍使用计算机视觉和图像处理技术进行条形码检测的必要步骤,并演示使用Python编程语言和 ...
- 使用Python,OpenCV查找图像中的最亮点
Python,OpenCV找出图像中的最亮点 1. 原理 2. 优化 3. 效果图 4. 源码 参考 这篇博客将向您展示如何使用Python和OpenCV查找图像中的最亮点,以及应用单行预处理代码-- ...
- 使用Python,OpenCV从图像中删除轮廓
使用Python,OpenCV从图像中删除轮廓 1. 效果图 2. 步骤 3. 源码 4. 参考 1. 使用Python.OpenCV计算轮廓的中心并标记 2. 使用Python.OpenCV检测轮廓 ...
- 使用Python,OpenCV寻找图像中的轮廓
使用Python和OpenCV查找图像中的形状 1. 效果图 2. 步骤 3. 源码 参考 这篇博客将讨论使用Python和OpenCV查找图像中的形状,具体是 cv2.inRange在图像中查找形状 ...
- 1.2 检测和测量图像中的圆形目标
此示例说明如何自动检测图像中的圆形目标并可视化检测到的圆. 步骤 1:加载图像 读取并显示包含各种颜色的圆形塑料片的图像.除了有大量要检测的圆之外,从圆检测的角度来看,此图像还有一些有趣的特点: 有不 ...
- OpenCV在图像中寻找轮廓的实例(附完整代码)
OpenCV在图像中寻找轮廓的实例 OpenCV在图像中寻找轮廓的实例 OpenCV在图像中寻找轮廓的实例 #include "opencv2/imgcodecs.hpp" #in ...
- OpenCV在图像中寻找轮廓
OpenCV在图像中寻找轮廓 在图像中寻找轮廓 目标 代码 结果 在图像中寻找轮廓 目标 在本教程中,您将学习如何: 使用OpenCV函数cv :: findContours 使用OpenCV函数cv ...
- OpenCV在图像中添加文字,画点,画直线
OpenCV在图像中添加文字,画点,画直线 [尊重原创,转载请注明出处] http://blog.csdn.net/guyuealian/article/details/77870983 #inclu ...
最新文章
- 程序员每天工作摸鱼俩小时,月薪35K?
- PyTorch与TensorFlow特性对比
- 【Linux 内核 内存管理】优化内存屏障 ① ( barrier 优化屏障 | 编译器优化 | CPU 执行优化 | 优化屏障源码 barrier 宏 )
- 扎心一问:分库分表就能无限扩容吗?
- 从产品角度聊一聊疯狂猜图为何这么火
- 【原创】自动更新程序2--更新程序的主窗体(技术:spring.net+三层架构+webservice+IrisSkin2换肤)...
- MySQL提高插入数据的效率(结合JDBC)
- PCD Lesson3:PCD文件的读取
- Java后端开发需要学什么
- 银河麒麟桌面系统V10解决微信无法登录
- my soft_macsoft
- Intellij IDEA 提示 Cannot access com... 解决办法
- HCIP考试-华为证书安全方向已取得
- 银行安防视频监控系统设计
- VC中三种常见中文内码的转换方法(GB2312/GBK/BIG5)
- BLS 签名和基于 BLS 签名的门限签名
- AES加解密(ECB模式)
- 阿里的Java 开发,拿那么高工资,每天都在干啥?
- 基于Intel 82571芯片的网卡介绍
- 笔试强训day25(数根,星际密码)