OpenCV实现抠图工具

本文实例为大家分享了OpenCV实现抠图工具的具体代码,供大家参考,具体内容如下

在计算机图像领域,我们经常需要做一些抠图的工作,将图像中的目标感兴趣区域提取出来,剔除其他冗余的背景元素,以实现计算机视觉的各项功能(如车辆检测、人脸检测等)。如果纯粹使用美图秀秀等工具类软件的话,由于工具类软件将图像处理中各种可能用到的功能都集成在了一起,所以纯粹做抠图的话效率很低。现在我们就用 OpenCV 来实现一段简易的抠图程序,只需要在画面上选定目标的感兴趣区域,该目标就会被自动按序号保存。

代码如下,同时包含有通俗易懂的注释:

#include <io.h>
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <opencv.hpp>
 
// 抠图是单目标还是多目标,若为单目标请将下面这行文字取消注释,反之请注释这段文字。
// #define SINGLE_OBJECT
 
#define TRUE 1     // 逻辑真
#define FALSE 0   // 逻辑假
 
#define CODE_ESC 27     // ESC 键的编码
#define CODE_SPC 32    // 空格键的编码
 
#define STATUS_WAIT 0  // 抠图等待状态
#define STATUS_PROC 1     // 抠图进行状态
#define STATUS_DONE 2    // 抠图完成状态
 
#define VIDEO_FILENAME "capture-1.mp4"          // 视频流文件名
 
static int m_x1     = 0;    // 鼠标指针坐标(起点 x)
static int m_x2     = 0;    // 鼠标指针坐标(终点 x)
static int m_y1     = 0;    // 鼠标指针坐标(起点 y)
static int m_y2     = 0;     // 鼠标指针坐标(终点 y)
static int m_status = STATUS_WAIT;              // 当前抠图状态指示
 
static void on_mouse(int, int, int, int, void*);// 鼠标回调
 
// 主程序
int main(void)
{
    int        end    = 0;         // 指示是否结束程序
    int        next   = 0;         // 指示是否切换到下一张图片
    int        code   = 0;        // 存储按键编码
    int        count  = 0;        // 存储目标计数
    int        frame  = 0;         // 视频帧号(用于间隔采样)
    int        maxCol = 0;             // 图像最大列数(= 图像宽度 - 1)
    int        maxRow = 0;                      // 图像最大行数(= 图像高度 - 1)
    CvCapture* pVideo = NULL;          // 视频流对象
    IplImage*  pFrame = NULL;           // 视频帧图像(用于样本存储)
    IplImage*  pFrmCp = NULL;           // 视频帧图像(用于屏幕显示)
    CvPoint    pt1    = cvPoint(0, 0);          // 矩形框对角坐标点 1
    CvPoint    pt2    = cvPoint(0, 0);          // 矩形框对角坐标点 2
    CvRect     r      = cvRect(0, 0, 0, 0);     // 感兴趣区域矩形框
    char       seq[]  = "-2147483648";          // 目标计数的字串形式
    char       fil[]  = "data\\-2147483648.jpg";// 文件名字串
 
    // 载入视频流
    pVideo = cvCreateFileCapture(VIDEO_FILENAME);
    if (!pVideo)
    {
        return -1;
    } // if (!pVideo)
 
    // 创建数据存储目录
    if (_access("data", 0) != 0)
    {
        system("md data");
    } // if (_access())
 
    // 获取首帧图像,并创建拷贝,同时得到最大列数和行数,方便之后使用
    pFrame = cvQueryFrame(pVideo);
    if (pFrame)
    {
        pFrmCp = cvCreateImage(cvGetSize(pFrame), 8, pFrame->nChannels);
        maxCol = pFrmCp->width - 1;
        maxRow = pFrmCp->height - 1;
    } // if (pFrame)
    else
    {
        cvReleaseCapture(&pVideo);
        return -1;
    } // else
 
    // 设置显示窗口,并设置鼠标回调
    cvNamedWindow("Monitor", CV_WINDOW_AUTOSIZE);
    cvSetMouseCallback("Monitor", on_mouse, NULL);
 
    // 其他初始化
    end = FALSE;
    count = 0;
    frame = 0;
 
    while (!end && pFrame)
    {
        next = FALSE;
        while (!next && !end)
        {
            // 将原始视频图像复制到拷贝区域中(清除已将图像进行污染的线条、矩形框等)
            cvCopy(pFrame, pFrmCp, NULL);
            if (STATUS_WAIT == m_status)
            {
                // 等待抠图状态。画出横向和纵向的参考线
                cvLine(pFrmCp, cvPoint(m_x1, 0), cvPoint(m_x1, maxRow), CV_RGB(0, 255, 0));
                cvLine(pFrmCp, cvPoint(0, m_y1), cvPoint(maxCol, m_y1), CV_RGB(0, 255, 0));
            } // if (STATUS_WAIT)
            else if (STATUS_PROC == m_status)
            {
                // 抠图过程中。画出当前选定的感兴趣区域
                pt1 = cvPoint(m_x1, m_y1);
                pt2 = cvPoint(m_x2, m_y2);
                cvRectangle(pFrmCp, pt1, pt2, CV_RGB(0, 255, 0));
            } // else if (STATUS_PROC)
            else if (STATUS_DONE == m_status)
            {
                // 抠图完毕,获得感兴趣区域并按编号保存样本
                r = cvRect(
                    m_x1,
                    m_y1,
                    m_x2 - m_x1 + 1,
                    m_y2 - m_y1 + 1
                    ); // 矩形感兴趣区域
                if (r.width > 30 && r.height > 30)
                {
                    // 区域达到了一定大小,抠图有效,保存感兴趣区域样本
                    ++count;
                    cvSetImageROI   (pFrame, r);
                    sprintf_s       (seq, "%d", count);
                    strcpy_s        (fil, "data\\");
                    strcat_s        (fil, seq);
                    strcat_s        (fil, ".jpg");
                    cvSaveImage     (fil, pFrame, 0);
                    cvResetImageROI (pFrame);
 
#ifdef SINGLE_OBJECT
                    m_next = TRUE;
#endif
                } // if (r.width)
                
                // 恢复抠图等待状态
                m_status = STATUS_WAIT;
            } // else if (STATUS_DONE)
 
            cvShowImage("Monitor", pFrmCp);
            code = cvWaitKey(10);
            if (CODE_SPC == code)
            {
                next = TRUE;
            } // if (CODE_SPC)
            else if (CODE_ESC == code)
            {
                end = TRUE;
            } // else if (CODE_ESC)
        } // while (!next)
 
        if (next)
        {
            do
            {
                pFrame = cvQueryFrame(pVideo);
                ++frame;
            } while (pFrame && frame % 60 != 0); // do...while
        } // if (next)
    } // while (!end)
 
    cvDestroyAllWindows();
    cvReleaseImage(&pFrmCp);
    cvReleaseCapture(&pVideo);
 
    return 0;
} // main()
 
 
// 鼠标事件回调
void on_mouse(int event, int x, int y, int flags, void* param)
{
    switch (flags)
    {
    case CV_EVENT_MOUSEMOVE:
        if (STATUS_WAIT == m_status)
        {
            // 等待状态,确定感兴趣区域起点
            m_x1 = x, m_y1 = y;
        } // if (STATUS_WAIT)
        else if (STATUS_PROC == m_status)
        {
            // 捕捉状态,确定感兴趣区域终点
            m_x2 = x, m_y2 = y;
        } // else if (STATUS_PROC)
        break;
 
    case CV_EVENT_LBUTTONDOWN:
        if (STATUS_WAIT == m_status)
        {
            // 等待状态按下鼠标,进入捕捉状态,固定起点
            m_x1 = x, m_y1 = y;
            m_status = STATUS_PROC;
        } // if (STATUS_WAIT)
        else if (STATUS_PROC == m_status)
        {
            // 捕捉状态按下鼠标,捕捉完成,固定终点
            m_x2 = x, m_y2 = y;
            m_status = STATUS_DONE;
        } // else if (STATUS_PROC)
        break;
    } // switch
} // on_mouse()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Opencv使用鼠标任意形状的抠图

    本文实例为大家分享了Opencv使用鼠标任意形状抠图的具体代码,供大家参考,具体内容如下 主要的方法思路是:首先利用鼠标在图上画任意形状,利用掩码将任意形状抠出来 主要难点是怎么填充,因为鼠标在画线的时候,滑动越快,点是不连续的,利用floodFill和drawContours都是没有办法进行填充的,从另一个方面想,一个面是由很多个点组成的,虽然鼠标滑动保存下来的就是一系列点,可以利用这一系列点构成一个面,利用面的性质进行填充就比较简单了. 一.首先使用鼠标点击事件,鼠标点击事件的函数为: vo

  • OpenCV实现简单套索工具

    Photoshop中的套索工具通过鼠标多次点击可以选中一个任意多边形的区域,然后单独对这块区域进行编辑,下面就使用OpenCV实现一个简单的功能,模拟Photoshop中的套索工具. 这里的套索工具通过鼠标左键在图片上多次点击创建任意多个点,右键点击后将这些点连成封闭的多边形,形成一块待编辑的区域,键盘方向键控制该区域的移动,从而将该区域内的图像复制到原图像的其他地方. 首先定义下列全局变量 const char* winName = "TaoSuoTool";//窗口名称 cv::M

  • OpenCV实现抠图工具

    本文实例为大家分享了OpenCV实现抠图工具的具体代码,供大家参考,具体内容如下 在计算机图像领域,我们经常需要做一些抠图的工作,将图像中的目标感兴趣区域提取出来,剔除其他冗余的背景元素,以实现计算机视觉的各项功能(如车辆检测.人脸检测等).如果纯粹使用美图秀秀等工具类软件的话,由于工具类软件将图像处理中各种可能用到的功能都集成在了一起,所以纯粹做抠图的话效率很低.现在我们就用 OpenCV 来实现一段简易的抠图程序,只需要在画面上选定目标的感兴趣区域,该目标就会被自动按序号保存. 代码如下,同

  • Opencv实现抠图背景图替换功能

    本文实例为大家分享了Opencv实现抠图替换背景图的具体代码,供大家参考,具体内容如下 下面简单图片演示一下: 提取mask: ===> 替换背景:  + = python的opencv代码如下: # coding=utf-8 import cv2 import numpy as np img=cv2.imread('lp.jpg') img_back=cv2.imread('back.jpg') #日常缩放 rows,cols,channels = img_back.shape img_bac

  • python和opencv实现抠图

    本文实例为大家分享了python实现抠图的具体代码,供大家参考,具体内容如下 其中使用了opencv中的grabcut方法 直接上代码 # encoding:utf-8 # 图像提取 # create by import numpy as np import cv2 from matplotlib import pyplot as plt img = cv2.imread('1.jpg') mask = np.zeros(img.shape[:2], np.uint8) bgdModel = n

  • 3行Python代码实现图像照片抠图和换底色的方法

    1.项目背景 对于不会PS的小伙伴,抠图是一个难度系数想当高的活儿,某宝照片抠图和证件照换底色均价都是5元RMB,所以今天要介绍的这款神工具,只要 3 行代码 5 秒钟就可以完成高精度抠图,甚至都不用会代码,点两下鼠标就完成了. 这里介绍Remove Image Background工具,它基于 Python.Ruby 和深度学习技术开发,通过强大的 AI 人工智能算法实现自动识别出前景主体与背景图,分分钟秒秒钟完成抠图. 这款抠图工具有两种简单方式:在线抠图和Python代码抠图,介绍如下.

  • python+opencv边缘提取与各函数参数解析

    前情提要:作为刚入门机器视觉的小伙伴,第一节课学到机器视觉语法时觉得很难理解, 很多人家的经验,我发现都千篇一律,功能函数没解析,参数不讲解,就一个代码,所以在此将搜集的解析和案例拿出来汇总!!! 一.opencv+python环境搭建 其实能写python的就能写opencv,但是工具很总要,代码提示也很重要,你可能会用submit     vs等工具,submit编码个人觉得不够智能,vs的话过完年我学的方向不一致,所以没用 推荐 pycharm ,在项目setting中的项目解释器中安装

  • Python实现AI自动抠图实例解析

    一.简介 抠图是用PS? 用魔棒和快速选择工具? 遇到复杂背景怎么办? 最近发现一个神奇的工具--Remove Image Background https://www.remove.bg/zh 它是基于Python.Ruby和深度学习技术开发,通过强大的AI人工智能算法实现自动识别出前景主体与背景图,秒秒种完成抠图. 这款抠图工具有两种简单方式: 1.在线抠图 2.API代码抠图 二.在线抠图 1.打开remove.bg网站首页,可以上传本地图片,也可以选择网络图片的URL链接. 2.上传几秒

  • Python opencv医学处理的实现过程

    题目描述 利用opencv或其他工具编写程序实现医学处理. 实现过程 # -*- coding: utf-8 -*- ''' 作者 : 丁毅 开发时间 : 2021/5/9 16:30 ''' import cv2 import numpy as np # 图像细化 def VThin(image, array): rows, cols = image.shape NEXT = 1 for i in range(rows): for j in range(cols): if NEXT == 0:

  • Python opencv缺陷检测的实现及问题解决

    题目描述 利用opencv或其他工具编写程序实现缺陷检测. 实现过程 # -*- coding: utf-8 -*- ''' 作者 : 丁毅 开发时间 : 2021/4/21 15:30 ''' import cv2 import numpy as np from PIL import Image, ImageDraw, ImageFont import matplotlib.pyplot as plt #用于给图片添加中文字符的函数 def cv2ImgAddText(img, text, l

  • OpenCV使用GrabCut实现抠图功能

    目录 1.概述 2.代码示例 3.示例图片 1.概述 案例:使用OpenCV的GrapCut实现有用户交互的抠图 grabCut( InputArray img, InputOutputArray mask, Rect rect, InputOutputArray bgdModel, InputOutputArray fgdModel, int iterCount, int mode = GC_EVAL ); img --> 输入的三通道图像: mask --> 输入的单通道图像,初始化方式为

  • 你还在@微信官方?聊聊Python生成你想要的微信头像

    今天早上@微信官方突然火了, 一句"请给我一面国旗@微信官方" 刷遍朋友圈. 到底是什么呢? 我们先来看看朋友圈 当然,这只是零零散散的部分截图, 看到这些,一股热血洒了出来, 我兴致勃勃的准备发朋友圈, 请神仙微信官方给我也换个头像, 就在这时,我手贱, 一不小心刷了下朋友圈, 结果: 我,好(lei)高(ge)兴(qu)啊! 原来是套路啊, 后来仔细想想,也是, 微信官方 哪有那么多时间给我换头像. 当然, 这也激发了我的程序员思维, 别人能做,我为啥不能? 说干就干,拿起Pyth

随机推荐