C#描述-计算机视觉OpenCV(4):图像分割

C#描述-计算机视觉OpenCV(4):图像分割

    • 前言
    • 用 GrabCut 算法分割图像
    • 实例展示

前言

本文中如果有什么没说明的地方,大概率在前文中描述过了。
C#描述-计算机视觉OpenCV(1):基础操作
C#描述-计算机视觉OpenCV(2):图像处理
C#描述-计算机视觉OpenCV(3):重映射
上一章节我们通过波形来分析了图像,那么图像中的背景与主体在波形上会有怎样的呈现呢?

for (int k = 120; k < 400; k++)
            {
                int r = 390;
                XList4.Add(k);
                YList4.Add(img.At<Vec3b>(r, k)[1]);
                chart2.Series["Green"].Points.DataBindXY(XList4, YList4);
                XList5.Add(k);
                YList5.Add(img.At<Vec3b>(r, k)[2]);
                chart2.Series["Blue"].Points.DataBindXY(XList5, YList5);
                XList6.Add(k);
                YList6.Add(img.At<Vec3b>(r, k)[0]);
                chart2.Series["Red"].Points.DataBindXY(XList6, YList6);
                img.At<Vec3b>(r, k)[0] = 0;
                img.At<Vec3b>(r, k)[1] = 0;
                img.At<Vec3b>(r, k)[2] = 0;//检测线标记
            }

我们标记一条检测线并示波
在这里插入图片描述
色彩波形结果:
在这里插入图片描述

这种差别以为着我们可以通过数值的变化来捕捉图片中的物体,并且做出分割。

用 GrabCut 算法分割图像

物体通常有自己特有的颜色,通过识别颜色接近的区域,通常可以提取出这些颜色。OpenCV 提供了一种常用的图像分割算法,即 GrabCut 算法。GrabCut 算法比较复杂,计算量也很大,但结果通常很精确。如果要从静态图像中提取前景物体(例如从图像中剪切一个物体,并粘贴到另一幅图像),最好采用GrabCut 算法。
算法参数模型:
cv::Mat result; // 分割结果(四种可能的值)
cv::Mat bgModel,fgModel; // 模型(内部使用)
// GrabCut 分割算法
cv::grabCut(
image, // 输入图像
mask, // 分割结果
rectangle, // 包含前景的矩形
bgModel,fgModel, // 模型
X, // 迭代次数
cv::GC_INIT_WITH_RECT // 使用矩形
);
首先我们开出需要的模型:

Mat mask = new Mat();
Mat res = new Mat();
Mat bgM = new Mat();
Mat fgM = new Mat();

然后我们定义一个检测矩形区域:

Rect rectangle;
rectangle = new Rect(int X,int Y,int Width,int Height);

然后我们可以代入一个图像,使用GrabCut()方法,

Cv2.GrabCut(image, mask, rectangle, bgM, fgM, 5, GrabCutModes.InitWithRect);

并获得一个结果Mat类 mask。需要注意:这个mask可不代表分割完成的结果。
我们在函数的中用 InitWithRect 标志作为最后一个参数,表示将使用
带边框的矩形模型。矩形中输入/输出的分割图像可以是以下四个值之一。
1.GC_BGD:这个值表示明确属于背景的像素(例如本例中矩形之外的像素)。
2.GC_FGD:这个值表示明确属于前景的像素(本例中没有这种像素)。
3.GC_PR_BGD:这个值表示可能属于背景的像素。
4.GC_PR_FGD:这个值表示可能属于前景的像素(即本例中矩形之内像素的初始值)
也就是说我们的mask是一个判断是否为主题的结果的矩阵,我们还需要来操作读取才能完成图像分割,那么具体该如何操作呢?

实例展示

原图如下:
在这里插入图片描述
我们选取区域(200, 45, 150, 400)来做切割,这里面主体与背景非常清晰。

public void ColorDetector(Mat image)
        {
            Mat mask = new Mat();
            Mat res = new Mat();
            Mat bgM = new Mat();
            Mat fgM = new Mat();
            Rect rectangle;
            
            rectangle = new Rect(200, 45, 150, 400);
            Cv2.GrabCut(image, mask, rectangle, bgM, fgM, 5, GrabCutModes.InitWithRect);

            Mat result = new Mat(mask.Rows, mask.Cols, MatType.CV_8UC1);
            for (int i = 0; i < mask.Rows; i++)
            {
                for (int j = 0; j < mask.Cols; j++)
                {
                    byte v = mask.Get<byte>(j, i);
                    switch (v)
                    {
                        case 0:
                            result.Set<byte>(j, i, 0);
                            break;
                        case 1:
                            result.Set<byte>(j, i, 255);
                            break;
                        case 2:
                            result.Set<byte>(j, i, 50);
                            break;
                        case 3:
                            result.Set<byte>(j, i, 200);
                            break;
                    }
                }
            }
            Cv2.ImShow("grab", result);
        }

我们划分出四个结果类型的区域,来看看分割的是否准确:
在这里插入图片描述
通过色块可以看到,我们还是切割出来了的,找到我们需要的色块类型,进行还原,并将其他色块统一:

for (int i = 0; i < mask.Rows; i++)
            {
                for (int j = 0; j < mask.Cols; j++)
                {
                    byte v = mask.Get<byte>(j, i);
                    switch (v)
                    {
                        case 0:
                            result.Set<byte>(j, i, 0);
                            
                            break;
                        case 1:
                            result.Set<byte>(j, i, 0);
                           
                            break;
                        case 2:
                          
                            result.Set<byte>(j, i, 0);
                            break;
                        case 3:
                            result.At<Vec3b>(j, i)[0] = image.At<Vec3b>(j, i)[0];
                            result.At<Vec3b>(j, i)[1] = image.At<Vec3b>(j, i)[1];
                            result.At<Vec3b>(j, i)[2] = image.At<Vec3b>(j, i)[2];
                            //result.Set<byte>(j, i, 200);
                            break;
                    }
                }
            }

在这里插入图片描述
分割成功!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

docker 指定根目录 迁移根目录

docker 指定根目录 1、问题描述2、问题分析3、解决方法3.1、启动docker程序前就手动指定docker根目录为一个大的分区(支持动态扩容)&#xff0c;事前就根本上解决根目录空间不够问题3.1.0、方法思路3.1.1、docker官网安装文档3.1.2、下载docker安装包3.1.3、安装docker 26.1.03…

记一次从登录框到前台rce

接口未授权挖掘 在网站未登录的情况下&#xff0c;由于不知道后台接口。唯一办法通过js文件、路径扫描。通过这种收集方式使用burp进行批量扫描&#xff0c;分别探测GET/POST请求。观察响应包跟状态码。判断响应包&#xff0c;确定存在未授权后&#xff0c;再构造数据包。 2 突…

C++ | Leetcode C++题解之第64题最小路径和

题目&#xff1a; 题解&#xff1a; class Solution { public:int minPathSum(vector<vector<int>>& grid) {if (grid.size() 0 || grid[0].size() 0) {return 0;}int rows grid.size(), columns grid[0].size();auto dp vector < vector <int>…

机器学习笔记-18

异常检测问题 异常检测虽然主要用于无监督学习问题上&#xff0c;但是和监督学习问题很相似。 异常检测(Anomaly Detection)&#xff1a;给定正确样本集{ x ( 1 ) , x ( 2 ) . . . x ( n ) x^{(1)},x^{(2)}...x^{(n)} x(1),x(2)...x(n)}&#xff0c;记新样本即要检测的样本为…

NIO(非阻塞I/O)和IO(阻塞I/O)详解

文章目录 一、NIO&#xff08;Non-blocking I/O&#xff0c;非阻塞I/O&#xff09;1、Channel&#xff08;通道&#xff09;与Buffer&#xff08;缓冲区&#xff09;1.1、使用ByteBuffer读取文件1.2、ByteBuffer 方法1.2、ByteBuffer 结构1.3、字符串与 ByteBuffer 互转1.4 Sca…

代码随想录算法训练营DAY48|C++动态规划Part9|121.买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III

文章目录 121.买卖股票的最佳时机思路CPP代码 122.买卖股票的最佳时机II思路CPP代码 123.买卖股票的最佳时机III思路CPP代码 121.买卖股票的最佳时机 力扣题目链接 文章讲解&#xff1a;121.买卖股票的最佳时机 视频讲解&#xff1a;动态规划之 LeetCode&#xff1a;121.买卖股…

BJFUOJ-C++程序设计-实验3-继承和虚函数

A TableTennisPlayer 答案&#xff1a; #include<iostream> #include<cstring> using namespace std;class TableTennisPlayer{ private:string firstname;string lastname;bool hasTable;public:TableTennisPlayer(const string &, const string &, bool…

jupyter notebook使用与本地位置设置

本地安装好Anaconda之后&#xff0c;自带的有Jupter notebook。 使用jupyter notebook 使用jupyter notebook时&#xff0c;可以直接打开或者搜索打开&#xff1a; 打开后&#xff0c;我们生成的或者编辑的一些文件&#xff0c;都可以看到&#xff0c;如下&#xff1a; j…

HTML标签大全

本文是用于解释文章中使用的标签&#xff0c;方便萌新理解标签结构&#xff0c;也方便大佬忘了过来查一下~ 本文根据博客教学进度实时更新&#xff0c;可以收藏一下~ 文章目录 第二篇1.template2.div3. button 第三篇4.ul5.li 第二篇 第二篇链接 1.template <template&g…

计算机408备考-数据结构重要知识点-数据结构的定义

请关注一下B站账号&#xff1a;谭同学很nice&#xff01;后期更新发布在这个账号上。。【计算机408备考-数据结构重要知识点-数据结构的定义-哔哩哔哩】https://b23.tv/x7shjNf 数据是信息的载体。数据元素是数据的基本单位。一个数据元素可由若干数据项组成&#xff0c;数据项…

利用大语言模型(KIMI)构建控制信息模型

数字化的核心是数字化建模&#xff0c;为一个事物构建数字模型是一项十分复杂的工作。不同的应用场景&#xff0c;对事物的关注重点的不同的。例如&#xff0c;对于一个智能传感器而言&#xff0c;从商业的角度看&#xff0c;产品的信息模型中应该包括产品的类型&#xff0c;名…

ESD管 AZ5825-01F国产替代型号ESDA05CPX

已经有很多客户选用雷卯的ESDA05CPX替代Amazing 的 AZ5825-01F&#xff0c; 客户可以获得更好的价格和更快的交期&#xff0c;主要应用于对5V供电和4.5V供电电流较大的Vbus线路插拔保护等。 雷卯ESDA05CPX优势&#xff1a; 带回扫 &#xff0c;钳位电压Vc 低&#xff0c;IPP为…

逻辑漏洞:水平越权、垂直越权靶场练习

目录 1、身份认证失效漏洞实战 2、YXCMS检测数据比对弱&#xff08;水平越权&#xff09; 3、MINICMS权限操作无验证&#xff08;垂直越权&#xff09; 1、身份认证失效漏洞实战 上一篇学习了水平越权和垂直越权的相关基本知识&#xff0c;在本篇还是继续学习&#xff0c;这…

利用亚马逊云科技GenAI企业助手Amazon Q Business构建企业代码开发知识库

2024年五一节假日的前一天&#xff0c;亚马逊云科技正式重磅发布了云计算行业期待已久的服务——Amazon Q Business。Amazon Q Business是专为企业用户打造的一个开箱即用的完善而强大企业GenAI助手。企业用户只需要将Amazon Q Business连接到现有的企业内部数据源&#xff0c;…

整合文本和知识图谱嵌入提升RAG的性能

我们以前的文章中介绍过将知识图谱与RAG结合的示例&#xff0c;在本篇文章中我们将文本和知识图谱结合&#xff0c;来提升我们RAG的性能 文本嵌入的RAG 文本嵌入是单词或短语的数字表示&#xff0c;可以有效地捕捉它们的含义和上下文。可以将它们视为单词的唯一标识符——捕获…

文件传送协议

壹、文件传输协议FTP 一、FTP简介 文件传送协议FTP曾是互联网上使用最广泛的协议&#xff1b; 在互联网发展的早期阶段&#xff0c;用FTP传送文件约占整个互联网的通信量的三分之一&#xff1b;知道1995年&#xff0c;www的通信量才首次超过FTP。 FTP实现的是通过网络实现异…

EasyRecovery2024汉化版电脑数据恢复软件下载

EasyRecovery是一款功能强大的数据恢复软件&#xff0c;其主要功能包括但不限于以下几点&#xff1a; 硬盘数据恢复&#xff1a;能够扫描本地计算机中的所有卷&#xff0c;建立丢失和被删除文件的目录树&#xff0c;实现硬盘格式化、重新分区、误删数据、重建RAID等硬盘数据恢…

基于GWO灰狼优化的CNN-LSTM-Attention的时间序列回归预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1卷积神经网络&#xff08;CNN&#xff09;在时间序列中的应用 4.2 长短时记忆网络&#xff08;LSTM&#xff09;处理序列依赖关系 4.3 注意力机制&#xff08;Attention&#xff09; 4…

细说SVPWM原理及软件实现原理,关联PWM实现

细说SVPWM原理及软件实现原理&#xff0c;关联PWM实现 文章目录 细说SVPWM原理及软件实现原理&#xff0c;关联PWM实现1. 前言2. 基础控制原理回顾2.1 FOC 原理回顾2.2 细说 SVPWM2.2.1 矢量扇区计算2.2.2 矢量作用时间计算 2.2.3 如何理解 U4 U6 2/3Udc?2.2.4 如何理解 U4m…

Linux系统编程--信号与管道

1、信号与管道是什么&#xff1f; 首先了解信号与管道的意义&#xff0c;我们需要了解Linux系统中进程之间是如何通信的。Linux操作系统下&#xff0c;以进程为单位来分配或者管理资源&#xff0c;进程之间不能直接访问资源&#xff0c;因此&#xff0c;要求进程间的资源和信息…