IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> (有代码有案例)vs2019 opencv 找到图像最大轮廓用GrabCut算法进行图像分割 -> 正文阅读

[人工智能](有代码有案例)vs2019 opencv 找到图像最大轮廓用GrabCut算法进行图像分割

找图像分割的时候看到了GrabCut算法,但是大部分都是要人机交互用鼠标划分区域,想着先通过大轮廓把目标图像分割出来,排除背景干扰,然后对目标图像进一步细节处理。

配置好opencv环境后,按照如下代码,先通过形态学进行预处理,然后找到最大轮廓的正外接矩形,把这个矩形当成GrabCut算法中需要的参数进行分割,最后结果还不错。

函数原型:

void grabCut( InputArray img, InputOutputArray mask, Rect rect,
                           InputOutputArray bgdModel, InputOutputArray fgdModel,
                           int iterCount, int mode = GC_EVAL );

img: 输入图像,必须是8位3通道图像,在处理过程中不会被修改
mask: 掩码图像,用来确定哪些区域是背景,前景,可能是背景,可能是前景等。mask既可以作为输入也可以作为输出。作为输入时,mode要选择GC_INIT_WITH_MASK (=1);
? ? ? ? ? ? GCD_BGD (=0), 背景; ? ? ? ? ? ? ? ? ? ? ? ?GCD_FGD (=1),前景;

? ? ? ? ? ? GCD_PR_BGD (=2),可能是背景; ? ? ? GCD_PR_FGD(=3),可能是前景。
? ? ? ? ? ? 如果没有手工标记GCD_BGD 或者GCD_FGD,那么结果只会有GCD_PR_BGD和GCD_PR_FGD
rect: 包含前景的矩形,格式为(x, y, w, h)
bdgModel,fgdModel: 算法内部使用的数组,只需要创建两个大小为(1,65),数据类型为np.float64的数组

iterCount: 算法迭代的次数
mode: 用来指示grabCut函数进行什么操作:
? ? ? ? ? ? cv.GC_INIT_WITH_RECT (=0),用矩形窗初始化GrabCut;
? ? ? ? ? ? cv.GC_INIT_WITH_MASK (=1),用掩码图像初始化GrabCut。


算法调用流程:
(1)读取一张图片,用矩形标记出前景部分。
(2)调用grabCut(),获得分割结果。
(3)由于grabCut函数返回的分割结果,包含四种值:确定属于背景像素、可能属于背景像素、确定属于前景像素、可能属于前景像素。所以,根据需要,从返回结果中提取需要值。
(4)根据需要从结果提取需要的值(矩阵)后,通过掩码,对图片进行分割。

关于GrabCut算法可以参考以下文章:

OpenCV3学习(7.3)——图像分割之三(GrabCut算法)

// test1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <windows.h>
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/utils/logger.hpp>
#include <thread>
#include <stdio.h>
#include <string.h>
using namespace std;
using namespace cv;
int main()
{

    Rect boundRect;
    

    //【1】载入原图并显示
    Mat img = imread("C:\\Users\\lixiaowei\\Desktop\\2.jpg", 1); // 读入图像


    namedWindow("yuantu", WINDOW_NORMAL);
    imshow("yuantu", img);

    Mat gray1, binary1;
    cvtColor(img, gray1, COLOR_BGR2GRAY);

    threshold(gray1, binary1, 20, 255,THRESH_OTSU);
    namedWindow("s", WINDOW_NORMAL);
    imshow("s", binary1);
    Mat kernel1 = getStructuringElement(MORPH_RECT, cv::Size(9, 9), cv::Point(-1, -1));//定义闭运算算子
    erode(binary1, binary1, kernel1, Point(-1, -1),5);
    dilate(binary1, binary1, kernel1, Point(-1, -1),5);

    namedWindow("binary1", WINDOW_NORMAL);
    imshow("binary1", binary1);

    std::vector<std::vector<cv::Point>> contoursDest2;
    std::vector<Vec4i> hierarchy2;
    findContours(binary1, contoursDest2, hierarchy2, RETR_TREE, CHAIN_APPROX_NONE);

    Mat m = Mat::zeros(binary1.size(), CV_8UC1); //最小外接矩形画布  
    

    vector<double> g_dConArea(contoursDest2.size());
    for (int i = 0; i < contoursDest2.size(); i++)
    {
        //计算轮廓的面积
        g_dConArea[i] = contourArea(contoursDest2[i]);
    }
    //寻找面积最大的部分
    int max = 0;
    for (int i = 1; i < contoursDest2.size(); i++) {
        if (g_dConArea[i] > g_dConArea[max]) {
            max = i;
        }
    }

    //绘制轮廓
    drawContours(m, contoursDest2, max, Scalar(255), 1, 8, hierarchy2);
    boundRect = boundingRect(Mat(contoursDest2[max]));
    rectangle(m, Point(boundRect.x, boundRect.y), Point(boundRect.x + boundRect.width, boundRect.y + boundRect.height), Scalar(255), 8, 8);


    namedWindow("标注出矩形", WINDOW_NORMAL);
    imshow("标注出矩形",m );


    //【2】使用grabCut算法分割
    //循环执行3次,这个可以自己设置
    Mat result;
    Mat bgModel, fgModel;
    grabCut(img, result, boundRect, bgModel, fgModel, 1, GC_INIT_WITH_RECT);
    namedWindow("grab", WINDOW_NORMAL);
    imshow("grab", result);
    //threshold();//二值化就可以显示
    compare(result, GC_PR_FGD, result, CMP_EQ);
    //result=result&1; 两种方法
    namedWindow("result", WINDOW_NORMAL);
    imshow("result", result);

    //【3】显示分割前后的图像
    Mat foreground(img.size(), CV_8UC3, Scalar(255, 255, 255));
    img.copyTo(foreground, result);
    //img.copy(forground, result);
    namedWindow("foreground", WINDOW_NORMAL);
    imshow("foreground", foreground);
    waitKey(0);	
	
}


最后贴上图片:

?

?

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-06-08 19:03:35  更:2022-06-08 19:04:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:48:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码