iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >C#如何使用OpenCV剪切图像中的圆形和矩形
  • 611
分享到

C#如何使用OpenCV剪切图像中的圆形和矩形

2023-06-07 23:06:17 611人浏览 独家记忆
摘要

这篇文章主要介绍“C#如何使用OpenCV剪切图像中的圆形和矩形”,在日常操作中,相信很多人在C#如何使用OpenCV剪切图像中的圆形和矩形问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#如何使用OpenC

这篇文章主要介绍“C#如何使用OpenCV剪切图像中的圆形和矩形”,在日常操作中,相信很多人在C#如何使用OpenCV剪切图像中的圆形和矩形问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#如何使用OpenCV剪切图像中的圆形和矩形”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

前言

本文主要介绍如何使用OpenCV剪切图像中的圆形和矩形。

准备工作

首先创建一个WPF项目——WpfOpenCV,这里版本使用Framework4.7.2。

然后使用Nuget搜索【Emgu.CV】,如下图。

C#如何使用OpenCV剪切图像中的圆形和矩形

这里的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;              }            }            #endregion            if (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); //保存结果图   #endregion  src.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);  }}

然后运行项目,点击剪切矩形文件。

C#如何使用OpenCV剪切图像中的圆形和矩形

然后到debug文件夹下,查看结果。

测试结果如下图所示:

C#如何使用OpenCV剪切图像中的圆形和矩形

图中红线为检测到矩形后,手动画上去的矩形轮廓。

使用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剪切图像中的圆形和矩形就已经介绍完了。

到此,关于“C#如何使用OpenCV剪切图像中的圆形和矩形”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: C#如何使用OpenCV剪切图像中的圆形和矩形

本文链接: https://www.lsjlt.com/news/250415.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C#如何使用OpenCV剪切图像中的圆形和矩形
    这篇文章主要介绍“C#如何使用OpenCV剪切图像中的圆形和矩形”,在日常操作中,相信很多人在C#如何使用OpenCV剪切图像中的圆形和矩形问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#如何使用OpenC...
    99+
    2023-06-07
  • Python OpenCV基于霍夫圈变换算法如何检测图像中的圆形
    小编给大家分享一下Python OpenCV基于霍夫圈变换算法如何检测图像中的圆形,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!第一章:霍夫变换检测圆①...
    99+
    2023-06-22
  • 如何在C#项目中利用OpenCV对图片中人物的头像进行剪切
    这篇文章主要介绍了如何在C#项目中利用OpenCV对图片中人物的头像进行剪切,此处给大家介绍的非常详细,对大家的学习或工作具有一定的参考价值,需要的朋友可以参考下:准备工作首先创建一个Wpf项目——OpenCV_Face_Wpf,这里版本使...
    99+
    2023-06-06
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作