這篇文章主要介紹“C#如何使用OpenCV剪切圖像中的圓形和矩形”,在日常操作中,相信很多人在C#如何使用OpenCV剪切圖像中的圓形和矩形問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”C#如何使用OpenCV剪切圖像中的圓形和矩形”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!
10年積累的成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站策劃后付款的網(wǎng)站建設(shè)流程,更有新津縣免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。本文主要介紹如何使用OpenCV剪切圖像中的圓形和矩形。
首先創(chuàng)建一個(gè)Wpf項(xiàng)目——WpfOpenCV,這里版本使用Framework4.7.2。
然后使用Nuget搜索【Emgu.CV】,如下圖。
這里的Emgu.CV選擇4.3.0.3890版本,然后安裝Emgu.CV和Emgu.CV.runtime.windows。
現(xiàn)在,我們進(jìn)入項(xiàng)目,進(jì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ù)里,我們先將圖像進(jìn)行縮放,這樣可以有效的減少檢測(cè)到的矩形數(shù)量。
再將圖片處理成灰度模式,然后再高斯模糊,再邊緣化。
然后,我們就可以在圖片里查找圖形輪廓了,當(dāng)輪廓有三個(gè)頂點(diǎn),那么它是三角形,如果有四個(gè)頂點(diǎn),那么它是四邊形;我們要截取矩形,所以這里要加一個(gè)角度的判斷,四個(gè)角必須都在80-100度之間。
取到了頂點(diǎn)后,在依據(jù)頂點(diǎn)剪切圖片就可以了。
下面是截取矩形的代碼,代碼中只截取了寬度較大的那個(gè)矩形。
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 取三角形和矩形的頂點(diǎn)坐標(biāo) 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個(gè)頂點(diǎn):三角形 { System.Drawing.Point[] pts = approxContour.ToArray(); triangleList.Add(new Triangle2DF(pts[0], pts[1], pts[2])); } else if (approxContour.Size == 4) //輪廓有4個(gè)頂點(diǎn) { #region 檢測(cè)角度,如果角度都在 [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(); //這里對(duì)取到的頂點(diǎn)坐標(biāo)進(jìn)行了加寬,因?yàn)榫匦慰赡艽嬖诮嵌龋@里沒有進(jìn)行角度旋轉(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è)置興趣點(diǎn)—ROI(region of interest ) var clone = src.Clone(); CvInvoke.Imwrite("剪切的矩形圖片.bmp", clone); //保存結(jié)果圖 #endregion src.Dispose(); srcNewSize.Dispose(); grayImage.Dispose(); }
然后編寫一個(gè)打開文件的函數(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); } }
然后運(yùn)行項(xiàng)目,點(diǎn)擊剪切矩形文件。
然后到debug文件夾下,查看結(jié)果。
測(cè)試結(jié)果如下圖所示:
圖中紅線為檢測(cè)到矩形后,手動(dòng)畫上去的矩形輪廓。
編寫矩形剪切函數(shù)——CutCircleImage。
函數(shù)里,我們依然先將圖像進(jìn)行縮放,為了有效的減少檢測(cè)到的圓形數(shù)量。
再將圖片處理成灰度模式,然后再高斯模糊。
然后再使用霍夫圓檢測(cè)函數(shù),獲取圓的圓心和半徑。
最后再根據(jù)圓心和半徑計(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); //霍夫圓檢測(cè) 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è)置興趣點(diǎn)—ROI(region of interest ) var clone = srcNewSize.Clone(); CvInvoke.Imwrite("剪切的圓形圖片.bmp", clone); //保存結(jié)果圖 src.Dispose(); srcNewSize.Dispose(); grayImage.Dispose(); }
運(yùn)行項(xiàng)目進(jìn)行測(cè)試,結(jié)果如下:
----------------------------------------------------------------------------------------------------
到此,C#使用OpenCV剪切圖像中的圓形和矩形就已經(jīng)介紹完了。
到此,關(guān)于“C#如何使用OpenCV剪切圖像中的圓形和矩形”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
網(wǎng)站題目:C#如何使用OpenCV剪切圖像中的圓形和矩形-創(chuàng)新互聯(lián)
網(wǎng)站路徑:http://vcdvsql.cn/article4/dgdeoe.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供移動(dòng)網(wǎng)站建設(shè)、標(biāo)簽優(yōu)化、服務(wù)器托管、動(dòng)態(tài)網(wǎng)站、關(guān)鍵詞優(yōu)化、營(yíng)銷型網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容