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

news/2024/9/19 0:44:57/ 标签: 计算机视觉, 图像, c#, opencv, dnn, emgucv, vb.net

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

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.ppmy.cn/news/1525425.html

相关文章

ctfshow--信息收集题目全解

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文记录ctfshow信息收集部分打靶记录 web1 这题弱智&#xff0c;f12进入查看源码&#xff0c;flag在注释里。 (这告诉我们&#xff0c;开发者的注释我们也是可以看到的&#xff0c;所以版权&#xff0c;源码地址&…

个人随想:嵌入学习桌的智能学习与陪伴助手

随着大模型技术的快速发展&#xff0c;我们对于7B、70B、80B甚至405B等开源大模型已经不陌生。在有GPU支持的情况下&#xff0c;许多人会倾向选择更大参数的模型&#xff0c;因为通常参数越大&#xff0c;效果越好&#xff0c;这已成为行业共识。 . 然而&#xff0c;随着量化技…

.NET 一款在线解密Web.config的脚本

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等&#xff08;包括但不限于&#xff09;进行检测或维护参考&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

man命令详解

一、man命令简介&#xff1a; man是manual的缩写。操作手册之意。 本地的帮助文档称为man pages&#xff0c;这些操作手册随着软件安装而安装到本地&#xff0c;可以使用man命令进行查询。 随着软件包的安装有些操作手册会以文档的方式放在/usr/share/doc目录当中。…

网络设备安全

网络设备安全概况 交换机安全威胁&#xff1a;交换机是网络基础设备&#xff0c;负责网络通信数据包的交换传输 交换机面临的网络安全威胁&#xff1a; 路由器安全威胁 网络设备安全机制与实现技术 认证机制&#xff1a;为防止网络设备滥用&#xff0c;网络设备读用户身份进行…

c# socket通信实例

服务器端 主要代码 //服务器socket private Socket serverSocket; private void InitServerSocket() {//创建终结点&#xff08;EndPoint&#xff09;IPAddress ip IPAddress.Any;IPEndPoint ipe new IPEndPoint(ip, 10030);//创建 socket 并开始监听serverSocket new Soc…

PyQT开发总结

用PyQT开发了一个界面小程序&#xff0c;记录一下。 pyuic和pyrcc pyuic &#xff08;PYthon User Interface Compiler&#xff09;是一个命令行工具&#xff0c;用于将 Qt Designer 生成的 .ui 文件转换成 Python 代码。pyrcc 用于处理 Qt 资源文件&#xff08;如图片&#…

海外云手机有哪些推荐?

随着云手机的发展&#xff0c;越来越多的企业和个人开始使用云手机来满足他们的海外业务需求。用户可以通过云手机实现方便、快捷的海外访问&#xff0c;一般用来进行tiktok运营、亚马逊电商运营、海外社媒运营等操作。海外云手机平台有很多&#xff0c;以下是一些比较好的云手…

波场TRON领航者孙宇晨:区块链行业的青年先锋与标杆

​孙宇晨&#xff0c;作为波场TRON的创始人&#xff0c;是区块链行业中备受瞩目的青年榜样。他的成长历程和对区块链技术的贡献&#xff0c;展现了他在这个快速发展的领域中的领导力和远见。 孙宇晨的区块链旅程始于他对去中心化技术的强烈兴趣和信念。他早年在北京大学和宾夕法…

【系统架构设计师-2013年真题】案例分析-答案及详解

更多内容请见: 备考系统架构设计师-核心总结索引 文章目录 【材料1】问题1问题2【材料2】问题1问题2问题3问题4【材料3】问题1问题2问题3【材料4】问题1问题2问题3【材料5】问题1问题2问题3【材料1】 阅读以下关于企业应用系统集成架构设计的说明,在答题纸上回答问题1和问题…

为什么在 JSON 序列化中不使用 transient

有些小伙伴发现了&#xff0c;明明在返回的实体类中指定了属性为transient。为什么前端得到的返回json中还是有这个属性的值&#xff1f; 类&#xff1a; private String name; private transient String password;返回结果&#xff1a; { name:"刘大大", password:…

MyBatis-PlusDruid数据源

MyBatis-Plus简介 MyBatis-Plus&#xff08;简称MP&#xff09;是一个MyBatis的增强工具&#xff0c;它在MyBatis的基础上进行了增强而不改变其原有的功能&#xff0c;旨在简化开发、提高效率。以下是对MyBatis-Plus的详细简介&#xff1a; 一、基本概述 定义&#xff1a;MyBat…

主流无线物联网通信技术有哪些

主流无线物联网通信技术主要包括以下几种&#xff0c;以下是对它们的详细分析和介绍&#xff1a; 一、短距离无线通信技术 蓝牙&#xff08;Bluetooth&#xff09; 蓝牙是一种大容量近距离无线数字通信技术标准&#xff0c;旨在实现最高数据传输速率1Mbps、最大传输距离为10…

高效执行自动化用例:分布式执行工具pytest-xdist实战

01声明 在介绍pytest-xdist时&#xff0c;不讲任何原理&#xff0c;需要看原理的请移至官方&#xff1a;pytest-xdist PyPI 当我们自动化测试用例非常多的时候&#xff0c; 一条条按顺序执行会非常慢&#xff0c;pytest-xdist的出现就是为了让自动化测试用例可以分布式执行&am…

快速入门游戏领域,开发游戏需要哪些技术?

在这个充满创意和技术的时代&#xff0c;游戏行业成为众多创新人才追求梦想的热土。对于准备踏入这个充满挑战与机遇的领域的新人来说&#xff0c;了解游戏开发流程是至关重要的。 游戏市场蓬勃发展&#xff0c;游戏行业未来行情可观&#xff0c;在这个充满创意和技术的时代&a…

OpenCV进行灰度变换

在Python中,处理图像(包括灰度变换)通常通过第三方库来完成,比如OpenCV和Pillow(PIL的更新版)。这里将分别介绍如何使用这两个库来进行灰度变换。 使用OpenCV进行灰度变换 OpenCV是一个开源的计算机视觉和机器学习软件库,它提供了大量图像处理的功能。使用OpenCV将图像…

git分支合并

git分支合并 说明步骤 说明 假如目前有两个分支 : main分支 和 master分支,你要将main分支合并到master分支,现在你正处于main分支. $ git branch * mainmaster步骤 切换到 master 分支&#xff1a; 首先&#xff0c;你需要切换到 master 分支&#xff0c;因为合并操作是在目…

Python “集合” 100道实战题目练习,巩固知识、检查技术

本文主要是作为Python中列表的一些题目&#xff0c;方便学习完Python的集合之后进行一些知识检验&#xff0c;感兴趣的小伙伴可以试一试&#xff0c;含选择题、判断题、实战题、填空题&#xff0c;答案在第五章。 在做题之前可以先学习或者温习一下Python的列表&#xff0c;推荐…

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

大模型能否真正理解上下文?

人工智能咨询培训老师叶梓 转载标明出处 尽管对LLMs的评估涵盖了自然语言处理&#xff08;NLP&#xff09;的各个领域&#xff0c;但对它们理解上下文特征的语言能力的探讨却相对有限。为了填补这一空白&#xff0c;乔治城大学和苹果公司的研究者们共同提出了一种新的上下文理解…