C#使用OpenCV剪切圖像中的圓形和矩形的示例代碼
前言
本文主要介紹如何使用OpenCV剪切圖像中的圓形和矩形。
準備工作
首先創(chuàng)建一個Wpf項目——WpfOpenCV,這里版本使用Framework4.7.2。
然后使用Nuget搜索【Emgu.CV】,如下圖。

這里的Emgu.CV選擇4.3.0.3890版本,然后安裝Emgu.CV和Emgu.CV.runtime.windows。
使用OPenCV剪切矩形
現(xiàn)在,我們進入項目,進行OPenCV的調(diào)用。
首先引入命名空間,如下:
using Emgu.CV; using Emgu.CV.CvEnum; using Emgu.CV.Structure; using System.Drawing; using System.Windows.Forms;
然后編寫矩形剪切函數(shù)——CutRectangleImage。
函數(shù)里,我們先將圖像進行縮放,這樣可以有效的減少檢測到的矩形數(shù)量。
再將圖片處理成灰度模式,然后再高斯模糊,再邊緣化。
然后,我們就可以在圖片里查找圖形輪廓了,當輪廓有三個頂點,那么它是三角形,如果有四個頂點,那么它是四邊形;我們要截取矩形,所以這里要加一個角度的判斷,四個角必須都在80-100度之間。
取到了頂點后,在依據(jù)頂點剪切圖片就可以了。
下面是截取矩形的代碼,代碼中只截取了寬度最大的那個矩形。
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);
//將圖像轉(zhuǎn)換為灰度
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>(); //旋轉(zhuǎn)的矩形框
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();
//這里對取到的頂點坐標進行了加寬,因為矩形可能存在角度,這里沒有進行角度旋轉(zhuǎn),所以加寬了取值范圍就可以取到完整的圖了
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);//設(shè)置興趣點—ROI(region of interest )
var clone = src.Clone();
CvInvoke.Imwrite("剪切的矩形圖片.bmp", clone); //保存結(jié)果圖
#endregion
src.Dispose();
srcNewSize.Dispose();
grayImage.Dispose();
}
然后編寫一個打開文件的函數(shù),在成功打開文件后調(diào)用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文件夾下,查看結(jié)果。
測試結(jié)果如下圖所示:

圖中紅線為檢測到矩形后,手動畫上去的矩形輪廓。
使用OPenCV剪切圓形
編寫矩形剪切函數(shù)——CutCircleImage。
函數(shù)里,我們依然先將圖像進行縮放,為了有效的減少檢測到的圓形數(shù)量。
再將圖片處理成灰度模式,然后再高斯模糊。
然后再使用霍夫圓檢測函數(shù),獲取圓的圓心和半徑。
最后再根據(jù)圓心和半徑計算出最小矩形,然后將圓剪切并保存。
代碼如下:
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);
//將圖像轉(zhuǎn)換為灰度
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);//設(shè)置興趣點—ROI(region of interest )
var clone = srcNewSize.Clone();
CvInvoke.Imwrite("剪切的圓形圖片.bmp", clone); //保存結(jié)果圖
src.Dispose();
srcNewSize.Dispose();
grayImage.Dispose();
}
運行項目進行測試,結(jié)果如下:

----------------------------------------------------------------------------------------------------
到此,C#使用OpenCV剪切圖像中的圓形和矩形就已經(jīng)介紹完了。
代碼已經(jīng)傳到Github上了,歡迎大家下載。
Github地址:https://github.com/kiba518/OpenCv_CutImage
到此這篇關(guān)于C#使用OpenCV剪切圖像中的圓形和矩形的文章就介紹到這了,更多相關(guān)C#剪切圖像中的圓形和矩形內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#調(diào)用百度翻譯實現(xiàn)翻譯HALCON的示例
HALCON示例程序的描述部分一直是英文的,看起來很不方便。本文就使用百度翻譯實現(xiàn)翻譯HALCON,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-06-06
C#實現(xiàn)將數(shù)據(jù)導(dǎo)出到word或者Excel中的方法
這篇文章主要介紹了C#實現(xiàn)將數(shù)據(jù)導(dǎo)出到word或者Excel中的方法,涉及C#操作word及Excel格式文件的方法,具有一定參考借鑒價值,需要的朋友可以參考下2015-08-08

