EmguCV学习笔记 C# 11.6 图像分割

news2024/12/26 20:54:14

 版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。

EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。

教程VB.net版本请访问:EmguCV学习笔记 VB.Net 目录-CSDN博客

教程C#版本请访问:EmguCV学习笔记 C# 目录-CSDN博客

笔者的博客网址:https://blog.csdn.net/uruseibest

教程配套文件及相关说明以及如何获得pdf教程和代码,请移步:EmguCV学习笔记

学习VB.Net知识,请移步: vb.net 教程 目录_vb中如何用datagridview-CSDN博客

 学习C#知识,请移步:C# 教程 目录_c#教程目录-CSDN博客

11.6 图像分割

11.6.1 语义分割Fcn

FCN(Fully Convolutional Network)是一种流行的语义分割算法,它通过将传统的卷积神经网络转化为全卷积网络来实现像素级别的语义分割,将输入图像传入网络中,得到每个像素的标签,并根据标签来分割出不同的物体。FCN在语义分割任务中表现优秀,可以实现像素级别的精细分割,被广泛应用于自动驾驶、智能监控等领域。

【代码位置:frmChapter11】Button5_Click、getColorTable、showColorTable

        //语义分割fcn

        private void Button5_Click(object sender, EventArgs e)

        {

            //对象分类,object_detection_classes_pascal_voc.txt文件提供了21类对象(含background

            string[] classnames = System.IO.File.ReadAllLines("C:\\learnEmgucv\\fcn\\object_detection_classes_pascal_voc.txt");

            //获得输出颜色表

            Bgr[] colorTable = getColorTable();

            //显示颜色表及对应对象名称

            showColorTable(classnames, colorTable);

            //需要测试的图像文件

            Mat m = new Mat("C:\\learnEmgucv\\dnntest1.jpg", ImreadModes.Color);

            Single hm = m.Height;

            Single wm = m.Width;

            Net net;

            net = DnnInvoke.ReadNetFromCaffe("C:\\learnEmgucv\\fcn\\fcn8s-heavy-pascal.prototxt",

                                             "C:\\learnEmgucv\\fcn\\fcn8s-heavy-pascal.caffemodel"

                                            );

            Mat mcopy = new Mat();

            CvInvoke.Resize(m, mcopy, new Size(500, 500));

            Mat blob = DnnInvoke.BlobFromImage(mcopy, 1, new Size(500, 500),

                                       new MCvScalar(0,0,0), false, false);

            net.SetInput(blob);

            Mat mout = new Mat();

            mout = net.Forward();

            Single[,,,] fout;

            fout = (Single[,,,])mout.GetData();

            //通道数=21,即21类对象

            int chan = fout.GetLength(1);

            //高度=500

            int row = fout.GetLength(2);

            //宽度=500

            int col = fout.GetLength(3);

            //记录21个通道对应坐标点的最大值

            Matrix<Single> matrMaxValue = new Matrix<Single>(new Size(row, col));

            matrMaxValue.SetZero();

            记录对应通道号

            //Matrix<Single> matrMaxChan = new Matrix<Single>(new Size(row, col));

            //matrMaxChan.SetZero();

            //记录对应颜色

            Image<Bgr, byte> imgOut = new Image<Bgr, byte>(col, row);

            imgOut.SetZero();

            //遍历21个通道

            for (int c = 0; c < chan; c++)

                for (int h = 0; h < row; h++)

                    //遍历高度和宽度,获得对应坐标的值

                    for (int w = 0; w < col; w++)

                        //比较最大值

                        if (fout[0, c, h, w] > matrMaxValue[h, w])

                        {

                            //取得最大值

                            matrMaxValue[h, w] = fout[0, c, h, w];

                            取得通道号

                            //matrMaxChan[h, w] = c;

                            //最重要的是获取通道对应颜色表的值

                            imgOut[h, w] = colorTable[c];

                        }

            //显示输出的图像

            //ImageBox1.Image = imgOut.Mat;

            //设置掩膜

            Mat mask = new Mat();

            mask = imgOut.Mat;

            //掩膜大小必须和源图像一致

            CvInvoke.Resize(mask, mask, m.Size);

            //将上面的输出图像和源图像叠加

            Mat mFinalOut = new Mat();

            CvInvoke.AddWeighted(m, 0.3, mask, 0.7, 0, mFinalOut);

            ImageBox1.Image = mFinalOut;

        }

       //为了更好地观察,这里没有使用随机颜色

        private Bgr[] getColorTable()

        {

            Bgr[] newColors = new Bgr[21];

            newColors[0] = new Bgr(0, 0, 0);        //background

            newColors[1] = new Bgr(128, 0, 0);      //aeroplane

            newColors[2] = new Bgr(0, 128, 0);      //bicycle

            newColors[3] = new Bgr(128, 128, 0);    //bird

            newColors[4] = new Bgr(0, 0, 128);      //boat

            newColors[5] = new Bgr(128, 0, 128);    //bottle

            newColors[6] = new Bgr(0, 128, 128);    //bus

            newColors[7] = new Bgr(128, 128, 128);  //car

            newColors[8] = new Bgr(255, 0, 0);     //cat

            newColors[9] = new Bgr(0, 255, 0);     //chair

            newColors[10] = new Bgr(0, 0, 255);     //cow

            newColors[11] = new Bgr(255, 255, 0);   //diningtable

            newColors[12] = new Bgr(64, 0, 128);    //dog

            newColors[13] = new Bgr(192, 0, 128);   //horse

            newColors[14] = new Bgr(64, 128, 128);  //motorbike

            newColors[15] = new Bgr(192, 128, 128); //person

            newColors[16] = new Bgr(0, 64, 0);     //pottedplant

            newColors[17] = new Bgr(128, 64, 64);   //sheep

            newColors[18] = new Bgr(0, 192, 0);     //sofa

            newColors[19] = new Bgr(128, 192, 0);   //train

            newColors[20] = new Bgr(0, 64, 128);    //tvmonitor

            return newColors;

        }

        //显示颜色表及对象名称

        //参数1:对象名称的字符串数组

        //参数2bgr颜色数组

        private void showColorTable(string[] names, Bgr[] colors)

        {

            List<Mat> lstmoutV = new List<Mat>();

            for (int i = 0; i <= 20; i++)

            {

                Mat moutV = new Mat(40, 200, DepthType.Cv8U, 3);

                moutV.SetTo(new MCvScalar(colors[i].Blue, colors[i].Green, colors[i].Red));

                CvInvoke.PutText(moutV, names[i], new Point(20, 25), FontFace.HersheyTriplex, 0.4, new MCvScalar(255, 255, 255));

                lstmoutV.Add(moutV);

            }

            Mat mout = new Mat();

            //垂直方向拼接

            CvInvoke.VConcat(lstmoutV.ToArray(), mout);

            CvInvoke.Imshow("colortable", mout);

        }

输出结果如下图所示:

 

图11-4 FCN分割获得不同对象区域

11.6.2 实例分割 MASK RCNN

Mask RCNN是一种基于Faster R-CNN的实例分割算法,它是一种联合目标检测和语义分割的方法,能够同时检测图像中的对象并得到每个对象的位置、类别和像素级别的分割结果。Mask RCNN在实例分割任务中表现优秀,是目前最先进的实例分割算法之一,被广泛应用于自动驾驶、智能监控等领域。

【代码位置:frmChapter11】Button6_Click、getRadomColor

        //实例分割 mask rcnn

        private void Button6_Click(object sender, EventArgs e)

        {

            //对象分类,object_detection_classes_coco.txt文件提供了90类对象(含background

            string[] classnames;

            classnames = System.IO.File.ReadAllLines("C:\\learnEmgucv\\maskrcnn\\object_detection_classes_coco.txt");

            //需要测试的图像文件

            Mat m = new Mat("C:\\learnEmgucv\\dnntest.jpg", ImreadModes.Color);

            Single hm = m.Height;

            Single wm = m.Width;

            Net net;

            net = DnnInvoke.ReadNetFromTensorflow("C:\\learnEmgucv\\maskrcnn\\frozen_inference_graph.pb",

                                 "C:\\learnEmgucv\\maskrcnn\\mask_rcnn_inception_v2_coco_2018_01_28.pbtxt"

                                  );

            Mat mcopy = new Mat();

            mcopy = m.Clone();

            Mat blob;

            blob = DnnInvoke.BlobFromImage(mcopy, 1, new Size(500, 500),

                                           new MCvScalar(0, 0, 0), false, false);

            net.SetInput(blob);

            string[] names = new string[2];

            names[0] = "detection_out_final";

            names[1] = "detection_masks";

            //返回的mout包含两个mat

            VectorOfMat mout = new VectorOfMat();

            net.Forward(mout, names);

            //第一个mat标识返回的置信度候选框,是一个四维数组

            Mat moutBox = new Mat();

            moutBox = mout[0];

            //返回维度:

            //1维:1

            //2维:1

            //3维:100100个候选置信矩形框

            //4维:70?;1:对应类别;2:置信度;3-6:候选框位置(源图像百分比)

            Single[,,,] foutBox;

            foutBox = (Single[,,,])moutBox.GetData();

            //第二个mat标识返回的掩膜,是一个四维数组   

            Mat moutMask = new Mat();

            moutMask = mout[1];

            //返回维度:

            //1维:100100个对象对应的100个掩膜

            //2维:90,对象的置信度

            //3维:15,掩膜高度

            //4维:15,掩膜宽度

            Single[,,,] foutMask;

            foutMask = (Single[,,,])moutMask.GetData();

            int maskH = 15;   //foutMask.GetLength(2)

            int maskW = 15;  //foutMask.GetLength(3)

            //新建Mat,用来在这上面绘制掩膜

            Mat mbg = new Mat(new Size(m.Width, m.Height), DepthType.Cv8U, 3);

            mbg.SetTo(new MCvScalar(0, 0, 0));

            for (int i = 0; i < 100; i++)

            {

                //置信度

                Single conf = foutBox[0, 0, i, 2];

                //当置信度满足时

                if (conf > 0.53)

                {

                    //对应检测对象的序号

                    int objID = (int)foutBox[0, 0, i, 1];

                    Single ltX = foutBox[0, 0, i, 3] * wm; //左上角X

                    Single ltY = foutBox[0, 0, i, 4] * hm; //左上角Y

                    Single rbX = foutBox[0, 0, i, 5] * wm; //右下角X

                    Single rbY = foutBox[0, 0, i, 6] * hm; //右下角Y

                    Single w = rbX - ltX; //宽度

                    Single h = rbY - ltY; //高度

                    //绘制包围矩形框

                    CvInvoke.Rectangle(m, new Rectangle((int)ltX, (int)ltY,(int) w, (int)h), new MCvScalar(0, 0, 255), 1);

                    //绘制对象名称

                    CvInvoke.PutText(m, classnames[objID], new Point((int)ltX, (int)ltY - 10), FontFace.HersheyTriplex, 0.3, new MCvScalar(255, 0, 0));

                    //开始处理掩膜

                    Mat mmask = new Mat();

                    //掩膜大小为15*15,对应foutMask最后两个维度

                    Single[,] bmask = new Single[15, 15];

                    for (int j = 0; j < 15; j++)

                        for (int k = 0; k < 15; k++)

                            bmask[j, k] = foutMask[i, objID, j, k];

                    //将数组转为Mat

                    Matrix<Single> matrmask = new Matrix<Single>(bmask);

                    mmask = matrmask.Mat;

                    //大小放大与对应包围矩形框一致

                    CvInvoke.Resize(mmask, mmask, new Size((int)w, (int)h));

                    //二值化

                    CvInvoke.Threshold(mmask, mmask, 0.3, 255, ThresholdType.Binary);

                    //由于本身是CV32F,需要处理为CV8U,才能使用FindContours

                    mmask.ConvertTo(mmask, DepthType.Cv8U);

                    //定义关注区域,当修改关注区域时,也就修改了源图像

                    Mat mRoi = new Mat(mbg, new Rectangle((int)ltX, (int)ltY, (int)w, (int)h));

                    //查找轮廓

                    VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();

                    CvInvoke.FindContours(mmask, contours, null, RetrType.External, ChainApproxMethod.ChainApproxSimple);

                    //填充轮廓

                    CvInvoke.DrawContours(mRoi, contours, -1, getRadomColor(), -1);

                }

            }

            Mat mresult = new Mat();

            //加法

            CvInvoke.AddWeighted(m, 1, mbg, 0.4, 0, mresult);

            ImageBox1.Image = mresult;

        }

        //获得随机颜色

        private MCvScalar getRadomColor()

        {

            Random rd = new Random(DateTime.Now.Millisecond);

            byte r, g, b;

            b = (byte)rd.Next(256);

            g = (byte)rd.Next(256);

            r = (byte)rd.Next(256);

            return new MCvScalar(b, g, r);

        }

输出结果如下图所示:

 

图11-5 Mask RCNN 分割得到对象区域和类别

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2130601.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

宠物毛发对人体有什么危害?宠物空气净化器小米、希喂、352对比实测

作为一个呼吸科医生&#xff0c;我自己也养猫。软软糯糯的小猫咪谁不爱啊&#xff0c;在养猫的过程中除了欢乐外&#xff0c;也面临着一系列的麻烦&#xff0c;比如要忍耐猫猫拉粑粑臭、掉毛、容易带来细菌等等的问题。然而我发现&#xff0c;现在许多年轻人光顾着养猫快乐了&a…

Vue生命周期钩子在UniApp中的应用

1、Vue 3 生命周期钩子介绍 onMounted()//注册一个回调函数&#xff0c;在组件挂载完成后执行。onUpdated()//注册一个回调函数&#xff0c;在组件因为响应式状态变更而更新其 DOM 树之后调用。onUnmounted()//注册一个回调函数&#xff0c;在组件实例被卸载之后调用。onBefor…

西部数据发布的一款西数硬盘检测修复工具-支持WD-L/WD-ROYL板,能进行硬盘软复位,可识别硬盘查看或清除-供大家学习参考

使用方法: 1、运行WDR5.3正式版.exe 2、导入WDR5.3.key 3、PORTTALK.SYS放入系统目录 第一步:注册完打开软件 第二步:设置维修盘端口:点击设置--》端口--》会出现主要端口 ,次要端口 ,定制端口 USB。一般如果不是USB移动硬盘都选择“定制端口”

WebGL入门(019):WebGLSync 简介、使用方法、示例代码

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

轨迹预测(2)CVPR-24:基于社交互动角度表示的行人轨迹预测(代码已开源)

一&#xff0e;写在前面 今天要分享的是CVPR 2024上的一篇精彩的行人轨迹预测论文。这篇文章的灵感来源于海洋动物&#xff0c;它们通过回声定位来感知水下同伴的位置。研究者们构建了一种名为 SocialCircle 的全新基于角度的社交互动表示模型&#xff0c;用于动态反映行人相对…

MATLAB | R2024b更新了哪些好玩的东西?

Hey, 又到了一年两度的MATLAB更新时刻&#xff0c;MATLAB R2024b正式版发布啦&#xff01;&#xff0c;直接来看看有哪些我认为比较有意思的更新吧! 1 小提琴图 天塌了&#xff0c;我这两天才写了个半小提琴图咋画&#xff0c;MATLAB 官方就出了小提琴图绘制方法。 小提琴图…

从边缘到云端,合宙DTURTU打造无缝物联网解决方案

随着物联网&#xff08;IoT&#xff09;技术的飞速发展&#xff0c;万物互联的时代已经到来&#xff0c; 如何高效、稳定地连接边缘设备与云端平台&#xff0c;实现数据的实时采集、传输与处理&#xff0c;成为了推动物联网应用落地的关键。 DTU&#xff08;数据传输单元&…

Python面试宝典第48题:找丑数

题目 我们把只包含质因子2、3和5的数称作丑数&#xff08;Ugly Number&#xff09;。比如&#xff1a;6、8都是丑数&#xff0c;但14不是&#xff0c;因为它包含质因子7。习惯上&#xff0c;我们把1当做是第一个丑数。求按从小到大的顺序的第n个丑数。 示例 1&#xff1a; 输入…

单链表的查找与长度计算

注&#xff1a;本文只探讨"带头结点"的情况(查找思路类似循环找到第i-1 个结点的代码) 一.按位查找&#xff1a; 1.代码演示&#xff1a; 版本一&#xff1a; #include<stdio.h> #include<stdlib.h> ​ ​ //定义单链表结点类型 typedef struct LNo…

C语言 | Leetcode C语言题解之第401题二进制手表

题目&#xff1a; 题解&#xff1a; char** readBinaryWatch(int turnedOn, int* returnSize) {char** ans malloc(sizeof(char*) * 12 * 60);*returnSize 0;for (int i 0; i < 1024; i) {int h i >> 6, m i & 63; // 用位运算取出高 4 位和低 6 位if (h &…

针对网上nbcio-boot代码审计的actuator方法的未授权访问漏洞和ScriptEngine的注入漏洞的补救

针对网上下面文章的漏洞补救 奇安信攻防社区-代码审计之nbcio-boot从信息泄露到Getshell 一、未授权分析 在ShiroConfig中放开了actuator方法的未授权访问 org/jeecg/config/shiro/ShiroConfig.java:156 上面问题,先注释掉上面的未授权访问,实际就是代码注释掉 二、、RCE…

秒懂Linux之管道通信

目录 前言 进程间通信目的 管道通信 原理 匿名管道 测试样例 情况与特点 模拟进程池 命名管道 全部代码 前言 两个进程之间可以进行数据的直接传递吗&#xff1f;——不可以&#xff0c;进程必须得具备独立性。 进程间通信目的 数据传输&#xff1a;一个进程需要将…

odoo14 | 报错:Database backup error: Access Denied

这两天抽空想为自己快速做一个简单的管理系统&#xff0c;来信息化管理一下自己家里的一些菜谱、电视剧下载清单等事情&#xff0c;我又不想大动干戈的用Java写管理系统&#xff0c;我就想用已经手生了两年半的odoo快速搭一个系统用用得了&#xff0c;结果还遇上了这么个事 根…

Java设计模式—面向对象设计原则(四) ----->接口隔离原则ISP (完整详解,附有代码+案例)

文章目录 3.4 接口隔离原则(ISP)3.4.1 概述3.4.2 案列 3.4 接口隔离原则(ISP) Interface Segregation Principle&#xff0c;简称ISP 3.4.1 概述 客户端测试类不应该被迫依赖于它不使用的方法&#xff1b;一个类对另一个类的依赖应该建立在最小的接口上。 3.4.2 案列 面看…

PMP--一模--解题--21-30

文章目录 9.资源管理21、 [单选] 项目经理发现一个不可预料的高影响风险已经成为项目的一个因素&#xff0c;团队成员之间的自身利益导致问题得不到解决&#xff0c;项目经理必须快速行动&#xff0c;让团队重新集中精力&#xff0c;以便项目恢复进度&#xff0c;项目经理应该使…

通信工程学习:什么是LCAS链路容量调整机制

LCAS&#xff1a;链路容量调整机制 LCAS&#xff08;Link Capacity Adjustment Scheme&#xff09;链路容量调整机制是一种在ITU-T G.7042中定义的技术&#xff0c;旨在解决传统SDH&#xff08;同步数字体系&#xff09;网络在传输数据业务时带宽分配不灵活的问题。以下是LCAS链…

【 C++ 】C/C++内存管理

前言&#xff1a; &#x1f618;我的主页&#xff1a;OMGmyhair-CSDN博客 目录 一、C/C内存分布 二、C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free malloc&#xff1a; calloc&#xff1a; realloc&#xff1a; free&#xff1a; 三、C内存管理方式…

用Mapmost聚类图分析世界

聚类地图是一种数据可视化工具&#xff0c;能够帮助用户在地图上直观地显示大量地理数据点。当数据点过多时&#xff0c;单独显示每个点会使地图变得混乱&#xff0c;而聚类地图通过将相近的数据点聚集在一起&#xff0c;减少了视觉复杂性&#xff0c;便于分析和理解。聚类地图…

在Linux上安装中创中间件InforSuiteAS(二进制文件安装)

在Linux上安装中创中间件InforSuiteAS&#xff08;二进制文件安装&#xff09; 前言1、环境准备1.1 支持的操作系统1.2 依赖软件 2、安装步骤2.1 下载并解压安装包2.2 执行安装2.3 修改防火墙设置2.4 启动InforSuiteAS2.5 InforSuiteAS常用命令2.6 验证安装 3、常见问题及解决方…

【Petri网导论学习笔记】Petri网导论入门学习(三)

Petri网导论入门学习&#xff08;三&#xff09; Petri 网导论学习笔记&#xff08;三&#xff09;定义 1.4定义 1.5定义 1.6定义 1.7 Petri 网导论学习笔记&#xff08;三&#xff09; 如需学习转载请注明原作者并附本帖链接&#xff01;&#xff01;&#xff01; 如需学习转载…