日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

OpenCV實現摳圖工具_C 語言

作者:幸福de小陽 ? 更新時間: 2022-04-01 編程語言

本文實例為大家分享了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()

原文鏈接:https://blog.csdn.net/smallyang0613/article/details/49072783

欄目分類
最近更新