【C#】用EmguCV 绘制各种轮廓线

c# OpenCvSharp 轮廓绘制六步骤你学会了吗(六) 轮廓绘制通过下面6个步骤得出轮廓 1、读取图像 Cv2.ImRead(); 2、将图像转换为灰度图像 Cv2.CvtColor(); 3、对图像进行模糊处理 滤波Cv2.Blur(); 4、边缘检测Canny(); 5、查找轮廓Cv2.FindContours(); 6、绘制轮廓Cv2.DrawContours(); 你可以在C#中使用OpenCvSharp实现轮廓绘制。祝你成功! 阅读详情

一般在做影像处理时,为提升效率,常会将影像转为二值影像后再进行处理。
在EmguCV内有许多找轮廓线的方法,但是随着版本更新,不同版本的函数
不见得会一样,每次都要重新查询实在很麻烦,那不如把他们记下来。

版本概要:
EmguCV版本:3.2.0.2682
编译器版本: Visual Studio 2017 Community
方案平台: x64 (许多导致程式无法执行的原因是因为没有改执行平台!)

正文开始。
首先我们用小画家画了一张图来作为范本—一朵云。
因为形状奇特,非常适合用来说明。
这里写图片描述

1. BoundingBox: 可以框住全部范围的矩形。

这是没有经过旋转地矩形,有经过旋转的矩形在后面讨论。

using System;
using System.Windows.Forms;
using System.Drawing;

using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;


namespace Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            Image<Gray, byte> I = new Image<Gray, byte>(@"D:\Test\1.jpg");
            Image<Bgr, byte> DrawI = I.Convert<Bgr, byte>();

            Image<Gray, byte> CannyImage = I.Clone();
            CvInvoke.Canny(I, CannyImage, 255, 255, 5, true);

            MyCV.BoundingBox(CannyImage, DrawI);
            pictureBox1.Image = DrawI.Bitmap;
        }
    }

    public class MyCV
    {
        public static void BoundingBox(Image<Gray, byte> src, Image<Bgr, byte> draw)
        {
            using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
            {
                CvInvoke.FindContours(src, contours, null, RetrType.External,
                                      ChainApproxMethod.ChainApproxSimple);

                int count = contours.Size;
                for (int i = 0; i < count; i++)
                {
                    using (VectorOfPoint contour = contours[i])
                    {
                        Rectangle BoundingBox = CvInvoke.BoundingRectangle(contour);
                        CvInvoke.Rectangle(draw, BoundingBox, new MCvScalar(255, 0, 255, 255), 3);
                    }
                }
            }
        }
    }
}

这里写图片描述

注:后面的程式码仅写出操作的函数,省略主视窗及名称空间,请自行代换主视窗的程式码。

在这边常有看到一些范例程式会建议使用ApproxPolyDP这个方法,取得近似的形状,
经过测试,若是在一些精度需求不高的情况下可以这么做,但就这个云形的例子而言不建议这样做。
下面是采用ApproxPolyDP函数的程式码与结果。

public static void ApproxBoundingBox(Image<Gray, byte> src, Image<Bgr, byte> draw)
{
    using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
    {
        CvInvoke.FindContours(src, contours, null, RetrType.External,
                              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.05, true);
                Rectangle BoundingBox = CvInvoke.BoundingRectangle(approxContour);
                CvInvoke.Rectangle(draw, BoundingBox, new MCvScalar(255, 0, 255, 255), 3);
            }
        }
    }
}

这里写图片描述

可以看到有许多卷卷的地方,都被近似掉了,以至于框选出来的范围会失真。
但,若目标是长方形或三角形这种比较规则的形状,使用近似的方法可以提升执行的效率。

其实若是直接把轮廓线画出来就可以看得更清楚,近似后许多细节会消失。
以下是程式码与执行结果。

public static void DrawContour(Image<Gray, byte> src, Image<Bgr, byte> draw)
{
    using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
    {
        CvInvoke.FindContours(src, contours, null, RetrType.External,
                                ChainApproxMethod.ChainApproxSimple);

        int count = contours.Size;
        for (int i = 0; i < count; i++)
        {
            using (VectorOfPoint contour = contours[i])
            using (VectorOfPoint approxContour = new VectorOfPoint())
            {
                // 原始輪廓線
                CvInvoke.DrawContours(draw, contours, i, new MCvScalar(255, 0, 255, 255), 3);

                // 近似後輪廓線
                CvInvoke.ApproxPolyDP(contour, approxContour, 
                                      CvInvoke.ArcLength(contour, true) * 0.02, true);
                Point[] pts = approxContour.ToArray();
                for(int j=0; j<pts.Length; j++)
                {
                    Point p1 = new Point(pts[j].X, pts[j].Y);
                    Point p2;

                    if (j == pts.Length - 1)
                        p2 = new Point(pts[0].X, pts[0].Y);
                    else
                        p2 = new Point(pts[j+1].X, pts[j+1].Y);

                    CvInvoke.Line(draw, p1, p2, new MCvScalar(255, 0, 0, 0), 3);
                }
            }
        }
    }
}

这里写图片描述

2. ConvexHull: 可以框住区块的最小多边形。

public static void ConvexHull(Image<Gray, byte> src, Image<Bgr, byte> draw)
{
    using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
    {
        CvInvoke.FindContours(src, contours, null, RetrType.External,
                                ChainApproxMethod.ChainApproxSimple);

        int count = contours.Size;
        for (int i = 0; i < count; i++)
        {
            using (VectorOfPoint contour = contours[i])
            {
                PointF[] temp = Array.ConvertAll(contour.ToArray(),
                                                new Converter<Point, PointF>(Point2PointF));
                PointF[] pts = CvInvoke.ConvexHull(temp, true);

                for (int j = 0; j < pts.Length; j++)
                {
                    Point p1 = new Point((int)pts[j].X, (int)pts[j].Y);
                    Point p2;

                    if (j == pts.Length - 1)
                        p2 = new Point((int)pts[0].X, (int)pts[0].Y);
                    else
                        p2 = new Point((int)pts[j + 1].X, (int)pts[j + 1].Y);

                    CvInvoke.Line(draw, p1, p2, new MCvScalar(255, 0, 255, 255), 3);
                }
            }
        }
    }
}

private static PointF Point2PointF(Point P)
{
    PointF PF = new PointF
    {
        X = P.X,
        Y = P.Y
    };
    return PF;
}

这里写图片描述

3. MinAreaBoundingBox: 可框住区域的最小矩形。

这是可旋转的矩形,意即找到面积最小,又可以框住该区域的矩形。

public static void MinAreaBoundingBox(Image<Gray, byte> src, Image<Bgr, byte> draw)
{
    using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
    {
        CvInvoke.FindContours(src, contours, null, RetrType.External,
                                ChainApproxMethod.ChainApproxSimple);

        int count = contours.Size;
        for (int i = 0; i < count; i++)
        {
            using (VectorOfPoint contour = contours[i])
            {
                RotatedRect BoundingBox = CvInvoke.MinAreaRect(contour);
                CvInvoke.Polylines(draw, Array.ConvertAll(BoundingBox.GetVertices(), Point.Round), 
                                   true, new Bgr(Color.DeepPink).MCvScalar, 3);
            }
        }
    }
}

这里写图片描述

4. MinAreaCircle:可框住区域的最小圆形。

public static void MinAreaCircle(Image<Gray, byte> src, Image<Bgr, byte> draw)
{
    using (VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint())
    {
        CvInvoke.FindContours(src, contours, null, RetrType.External,
                                ChainApproxMethod.ChainApproxSimple);

        int count = contours.Size;
        for (int i = 0; i < count; i++)
        {
            using (VectorOfPoint contour = contours[i])
            {
                CircleF circle = CvInvoke.MinEnclosingCircle(contour);       
                CvInvoke.Circle(draw, new Point((int)circle.Center.X, (int) circle.Center.Y),
                                (int)circle.Radius, new MCvScalar(255, 0, 255, 255), 3);
            }
        }
    }
}

这里写图片描述
在EmguCV内一种轮廓线就一种画法。
真的是要足够熟练才能够驾驭这些函数唉!

像是可怜的小夏已经陷在这些函数内好几天了,真是头昏眼花,临表泣涕,不知所云。

翻译自:dotblogs.com.tw 夏恩的程式笔记

EmguCv多边形筛选  面积筛选:CvInvoke.ContourArea() 周长筛选:CvInvoke.ArcLength() 多边形筛选:CvInvoke.ApproxPolyDP() 多边形简化: public void btn_Filter_Click(object sender, EventArgs e) { if (ib_original.Image !=... 阅读详情

相关推荐

EmguCv学习_基本绘图函数

基本绘图函数 主要作用:标记,结果输出 EmguCV常用绘图函数: CvInvoke.Line()//------用于绘制直线 CvInvoke.Circle()//函数------用于绘制圆 CvInvoke.Rectangle()//函数------用于绘制矩形 CvInvoke.Ellipse()//函数------用于绘制椭圆 CvInvoke.PutText()//函数------用于添加文字 绘制直线-----CvInvoke.Line() Line(IIputOutputArra

qq_39112175的博客 2005

21-22轮廓绘制(EmguCV学习)

文章目录注意Code效果 注意 1、CvInvoke.FindContours()函数输入图像应该为二值图像,检测的轮廓针对的是白色物体(高亮部分);FindContours()函数会修改原图像; 2、hierarchy(层次结构) : 每个轮廓都有一个自己的层次结构;对每一个轮廓,hierarchy包含四个元素,表示同等级的后一个轮廓、前一个轮廓、子轮廓序号、父轮廓序号;在drawContour...

hello 2569

OpenCV轮廓发现及绘制轮廓(C#)

OpenCV轮廓发现及绘制轮廓(C#)

weixin_40671962的博客 2638

emgucv——findContours

emgucv——findContours

Hello World 8311

基于轮廓拟合的C# OpenCV-EmguCV圆形检测实例

在图像处理中,常常需要对圆形进行检测和定位。EmguCV是一个基于OpenCV的跨平台图像处理库,提供了丰富的图像处理算法和工具函数。本文将介绍如何使用EmguCV和C#编写程序实现基于轮廓拟合的圆形检测。其中,EvaluateCircle函数用于计算轮廓与拟合圆之间的差异度,可以使用最小二乘法或其它方法实现。首先,需要创建一个EmguCV项目并引入相应的dll文件。至此,我们完成了基于轮廓拟合的C# OpenCV-EmguCV圆形检测实例。基于轮廓拟合的C# OpenCV-EmguCV圆形检测实例。

2301_79365003的博客 597

emgucv4学习18---角点检测

目前的角点检测算法可归纳为 3 类:基于灰度图像的角点检测、基于二 值图像的角点检测、基于轮廓曲线的角点检测。角点是图像很重要的特征, 对图像图形的理解和分析有很重要的作用。其中基于灰度图像的角点检测又 可分为基于梯度、基于模板和基于模板梯度组合 3 类方法,其中基于模板的 方法主要考虑像素领域点的灰度变化,即图像亮度的变化,将与邻点亮度对 比足够大的点定义为角点。常见的基于模板的角点检测算法有 Kitchen-Rosenfeld 角点检测算法,Harris 角点检测算法、KLT 角点检测算...

qianxun 652

EmguCV学习笔记 C# 3.2 矩形

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。教程配套文件及相关说明获得pdf教程和代码。

学习微软 .net 技术开发 1128

Emgu.CV.CvInvoke函数

图像检测、Emgu.CV.CvInvoke函数 计算两个数组差值的绝对值 将整个图像或其选定区域添加到累加和 将两张图像或其选定区域添加到累加和 图像自适应阈值 两个数组的元素级的加运算 两个数组的元素级的加权相加运算 伪彩色映射 使用多边形逼近一个轮廓 计算一个轮廓周长或曲线长度 ...... 计算密集的光的流量 实现非金字塔的Lucas_Kanade稠密光流算法 估计固有的摄像机参数和外部参数的每个视图 计算各种有用的相机(传感器/镜头)的特点,使用计算相机校准矩阵,图像帧分辨率的像素和物理孔径大小 ...... 发现二维点集凸壳的使用Sklansky算法 发现轮廓的凸性缺陷。 将特定的图像轻微变大,然后以各种方式自动填充图像边界

EmguCV学习笔记 VB.Net 3.2 矩形

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。教程配套文件及相关说明获得pdf教程和代码。

学习微软 .net 技术开发 774

基于STM32平衡小车设计

随着智能硬件的发展,基于STM32的两轮智能平衡车作为一种新型的智能移动工具,具备较高的应用价值。本文旨在设计并实现一款基于STM32微控制器的智能平衡车系统,提升其稳定性和操控性,探索如何通过传感器数据和控制算法实现精确平衡控制。 本设计基于STM32微控制器,选择了STM32F103系列作为核心控制器,具有足够的处理能力和丰富的外设接口。系统通过MPU6050传感器获取三轴加速度和三轴陀螺仪数据,实现实时姿态检测。电机驱动部分采用合适的驱动模块,能够控制两个直流电机,并支持PWM调速。设计中还包括OL

m0_74026776的博客 2730

反激变压器设计学习笔记

反激变压器匝比感量设计

m0_55419117的博客 5263

[转载+原创]Emgu CV on C# (七) —— Emgu CV on 轮廓检测

轮廓检测 对于查找轮廓我们一般要对图像Canny检测。但是对于很特殊的场合其实我们还可以直接对二值化的图像进行轮廓的提取。 关键函数 1、cvFindContours Retrieves contours from the binary image and returns the number of retrieved contours. The pointer firstC...

weixin_30511039的博客 234

Unity3D 2022版如何一键安装Newtonsoft.Json?最新Package Manager教程

本文详细介绍了在Unity3D 2022及以上版本中,如何通过Package Manager一键安装和配置Newtonsoft.Json(Json.NET)。教程涵盖了从打开Package Manager、搜索并安装正确包源,到验证安装和基础使用的完整流程,旨在帮助开发者以现代化、可靠的方式集成这一强大的JSON处理框架,提升开发效率并规避手动导入的常见问题。

lg888的博客 921

[转载+原创]Emgu CV on C# (六) —— Emgu CV on Canny边缘检测

Canny边缘检测也是一种边缘检测方法,本文介绍了Canny边缘检测的函数及其使用方法,并利用emgucv方法将轮廓检测解算的结果与原文进行比较。 图像的边缘检测的原理是检测出图像中所有灰度值变化较大的点,而且这些点连接起来就构成了若干线条,这些线条就可以称为图像的边缘。Canny边缘检测算子是John F. Canny于1986年开发出来的一个多级边缘检测算法。 ...

weixin_30897079的博客 302

自定义串口通讯协议

自定义串口通讯协议的实现方法

qq_44826038的博客 2172

LVGL 实战:倒计时翻页钟

环境:LVGL 9.x + PC 模拟器。每个数字做成上下两半的卡片,秒变时用绕中缝翻页:上半旧页折叠下去、下半新页展开上来,配合阴影遮罩做出立体感。从 02:00 倒计时到 0,闪一下再重置。界面文案用英文(默认字体无中文)。

摸鱼专家 213

OpenCV 轮廓检测 - 技术文档 (C#)

通过以上操作,我们可以实现图像的轮廓检测和绘制。OpenCV结合Emgu CV提供了强大的轮廓检测功能,可以满足各种图像处理需求。更多高级操作和应用请参考OpenCV和Emgu CV官方文档。轮廓检测在图像处理中具有重要意义。它可以帮助我们识别和分析图像中的形状和对象。本技术文档介绍如何使用OpenCV结合C#进行轮廓检测和绘制。使用Canny边缘检测算法来检测图像中的边缘。将图像转换为灰度图像,以便进行边缘检测。绘制查找到的轮廓并显示结果。首先,我们需要读取图像。函数查找图像中的轮廓。

东城十三 747

ROS机器人未知环境自主探索功能包explore_lite总结

本系列文章主要针对ROS机器人常使用的未知环境自主探索功能包explore_lite展开全源码的详细解析,并进行概括总结。 本系列文章共包含六篇文章,前五篇文章主要介绍explore_lite功能包中 explore.cpp、costmap_tools.h、frontier_search.cpp、costmap_client.cpp等源码实现文件中全部函数的详细介绍,第六篇文章进行概括总结,包含自主探索功能包explore_lite的简介,实现未知环境自主探索功能的原理及流程总结,效果演示,使用功能包exp

慕羽★的博客 4461

EmguCV学习笔记 VB.Net 6.2 轮廓处理

EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。教程配套文件及相关说明获得pdf教程和代码。

学习微软 .net 技术开发 2030

SI案例分享--FPC(柔性电路板)信号仿真

设计高性能的柔性PCB时,由于采用了网格地的参考面构造,因此,需要按照特定的结构进行布局,才可以保证所需目标阻抗的稳定性,该结构的配置过程称为“Hatch Configuration”,合理的参数配置将有助于得到满意的设计效果。

一只豌豆象的博客 2829

TC3XX - MCAL知识点(二十):CAN MCAL配置及代码实战(CAN/CANFD/extenen CAN)

CAN驱动程序负责提供AUTOSAR指定的标准CAN通信服务。M_CAN单元是底层的CAN硬件单元,它由共享消息RAM(在AUTOSAR中称为硬件对象)的节点(在AUTOSAR中称为控制器)组成。CAN驱动提供以下服务:·初始化CAN控制器以控制CAN控制器的行为和状态·设置和修改CAN控制器的波特率配置·支持CAN和CAN FD帧的收发·在轮询和中断模式下,成功的帧传输通知,专用和FIFO消息的接收和总线事件通知·数据接收使用接收FIFO功能·假装网络模式处理·支持多读/写周期功能。

梦想技术家 3940

C# OpenCV学习笔记五之图像轮廓

原始图 轮廓图 相关代码如下             Image imageSource = new Image((Bitmap)loadPictureBox.Image);             Image imageGrayscale = imageSour

边城骆驼 -- 每天进步百分之一 9854

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Emgu CV4图像处理之轮廓查找与绘制15(C#)

4 添加项目引用Emgu.CV.dll、Emgu.CV.Platform.NetFramework.dll、System.Drawing.dll和System.Runtime.InteropServices.RuntimeInformation.dll。contourIds:要绘制contours中的那一条,一般遍历contours获取到,如contours[0]color:线条的颜色,如new McvScalar(0,255,0)contours:通过查找轮廓函数查找到的轮廓信息。win10 64位。

zxy13826134783的博客 1686

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Emgucv绘制图形

private void btnDrawPic_Click(object sender, EventArgs e) { //绘画图形初始化 Image img = new Image(200, 200, new Bgr(255, 255, 255));//创建一张白色的200*200的图片 Rectangle

朱朱家园 5564

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

上一篇: [Kafka]Monitor Kafka with jmxtrans
下一篇: SQL Server 2017 on Linux自动安装
daan5com
博客等级 码龄9年 3粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值