OpenCV实现抠图工具
本文实例为大家分享了OpenCV实现抠图工具的具体代码,供大家参考,具体内容如下
在计算机图像领域,我们经常需要做一些抠图的工作,将图像中的目标感兴趣区域提取出来,剔除其他冗余的背景元素,以实现计算机视觉的各项功能(如车辆检测、人脸检测等)。如果纯粹使用美图秀秀等工具类软件的话,由于工具类软件将图像处理中各种可能用到的功能都集成在了一起,所以纯粹做抠图的话效率很低。现在我们就用 OpenCV 来实现一段简易的抠图程序,只需要在画面上选定目标的感兴趣区域,该目标就会被自动按序号保存。
代码如下,同时包含有通俗易懂的注释:
#include#include #include #include #include #include // 抠图是单目标还是多目标,若为单目标请将下面这行文字取消注释,反之请注释这段文字。// #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){intend= 0; // 指示是否结束程序intnext= 0; // 指示是否切换到下一张图片intcode= 0; // 存储按键编码intcount= 0; // 存储目标计数intframe= 0; // 视频帧号(用于间隔采样)intmaxCol = 0; // 图像最大列数(= 图像宽度 - 1)intmaxRow = 0; // 图像最大行数(= 图像高度 - 1)CvCapture* pVideo = NULL; // 视频流对象IplImage*pFrame = NULL; // 视频帧图像(用于样本存储)IplImage*pFrmCp = NULL; // 视频帧图像(用于屏幕显示)CvPointpt1= cvPoint(0, 0); // 矩形框对角坐标点 1CvPointpt2= cvPoint(0, 0); // 矩形框对角坐标点 2CvRectr= cvRect(0, 0, 0, 0); // 感兴趣区域矩形框charseq[]= "-2147483648"; // 目标计数的字串形式charfil[]= "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_OBJECTm_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()
【OpenCV实现抠图工具】以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。
推荐阅读
- C++项目开发实现图书管理系统
- 使用Java实现一个JS脚本引擎
- Python基础|快速傅里叶变换及python代码实现
- 问答系统|简单问答系统实现原理 - 基于机器学习的
- 深度学习|【深度学习】经典网络-VGG复现(使用Tensorflow实现)
- docker|win11安装Docker玩转OpenCV梦的开始
- github|【GitHubDailyShare】现代机器学习系统的设计原理以及实现
- 前端实现复制功能
- C++|c++中string的模拟实现
- C/C++|C++中简单的string类的实现