您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關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()
看完上述內容,你們對OpenCV實現摳圖工具的代碼是什么有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。