溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

OpenCV實現(xiàn)摳圖工具的代碼是什么

發(fā)布時間:2022-01-19 13:21:29 來源:億速云 閱讀:144 作者:柒染 欄目:開發(fā)技術(shù)

今天就跟大家聊聊有關OpenCV實現(xiàn)摳圖工具的代碼是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

在計算機圖像領域,我們經(jīng)常需要做一些摳圖的工作,將圖像中的目標感興趣區(qū)域提取出來,剔除其他冗余的背景元素,以實現(xiàn)計算機視覺的各項功能(如車輛檢測、人臉檢測等)。如果純粹使用美圖秀秀等工具類軟件的話,由于工具類軟件將圖像處理中各種可能用到的功能都集成在了一起,所以純粹做摳圖的話效率很低。現(xiàn)在我們就用 OpenCV 來實現(xiàn)一段簡易的摳圖程序,只需要在畫面上選定目標的感興趣區(qū)域,該目標就會被自動按序號保存。

代碼如下,同時包含有通俗易懂的注釋:

#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  // 摳圖等待狀態(tài)
#define STATUS_PROC 1     // 摳圖進行狀態(tài)
#define STATUS_DONE 2    // 摳圖完成狀態(tài)
 
#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;              // 當前摳圖狀態(tài)指示
 
static void on_mouse(int, int, int, int, void*);// 鼠標回調(diào)
 
// 主程序
int main(void)
{
    int        end    = 0;         // 指示是否結(jié)束程序
    int        next   = 0;         // 指示是否切換到下一張圖片
    int        code   = 0;        // 存儲按鍵編碼
    int        count  = 0;        // 存儲目標計數(shù)
    int        frame  = 0;         // 視頻幀號(用于間隔采樣)
    int        maxCol = 0;             // 圖像最大列數(shù)(= 圖像寬度 - 1)
    int        maxRow = 0;                      // 圖像最大行數(shù)(= 圖像高度 - 1)
    CvCapture* pVideo = NULL;          // 視頻流對象
    IplImage*  pFrame = NULL;           // 視頻幀圖像(用于樣本存儲)
    IplImage*  pFrmCp = NULL;           // 視頻幀圖像(用于屏幕顯示)
    CvPoint    pt1    = cvPoint(0, 0);          // 矩形框?qū)亲鴺它c 1
    CvPoint    pt2    = cvPoint(0, 0);          // 矩形框?qū)亲鴺它c 2
    CvRect     r      = cvRect(0, 0, 0, 0);     // 感興趣區(qū)域矩形框
    char       seq[]  = "-2147483648";          // 目標計數(shù)的字串形式
    char       fil[]  = "data\\-2147483648.jpg";// 文件名字串
 
    // 載入視頻流
    pVideo = cvCreateFileCapture(VIDEO_FILENAME);
    if (!pVideo)
    {
        return -1;
    } // if (!pVideo)
 
    // 創(chuàng)建數(shù)據(jù)存儲目錄
    if (_access("data", 0) != 0)
    {
        system("md data");
    } // if (_access())
 
    // 獲取首幀圖像,并創(chuàng)建拷貝,同時得到最大列數(shù)和行數(shù),方便之后使用
    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
 
    // 設置顯示窗口,并設置鼠標回調(diào)
    cvNamedWindow("Monitor", CV_WINDOW_AUTOSIZE);
    cvSetMouseCallback("Monitor", on_mouse, NULL);
 
    // 其他初始化
    end = FALSE;
    count = 0;
    frame = 0;
 
    while (!end && pFrame)
    {
        next = FALSE;
        while (!next && !end)
        {
            // 將原始視頻圖像復制到拷貝區(qū)域中(清除已將圖像進行污染的線條、矩形框等)
            cvCopy(pFrame, pFrmCp, NULL);
            if (STATUS_WAIT == m_status)
            {
                // 等待摳圖狀態(tài)。畫出橫向和縱向的參考線
                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)
            {
                // 摳圖過程中。畫出當前選定的感興趣區(qū)域
                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)
            {
                // 摳圖完畢,獲得感興趣區(qū)域并按編號保存樣本
                r = cvRect(
                    m_x1,
                    m_y1,
                    m_x2 - m_x1 + 1,
                    m_y2 - m_y1 + 1
                    ); // 矩形感興趣區(qū)域
                if (r.width > 30 && r.height > 30)
                {
                    // 區(qū)域達到了一定大小,摳圖有效,保存感興趣區(qū)域樣本
                    ++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)
                
                // 恢復摳圖等待狀態(tài)
                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()
 
 
// 鼠標事件回調(diào)
void on_mouse(int event, int x, int y, int flags, void* param)
{
    switch (flags)
    {
    case CV_EVENT_MOUSEMOVE:
        if (STATUS_WAIT == m_status)
        {
            // 等待狀態(tài),確定感興趣區(qū)域起點
            m_x1 = x, m_y1 = y;
        } // if (STATUS_WAIT)
        else if (STATUS_PROC == m_status)
        {
            // 捕捉狀態(tài),確定感興趣區(qū)域終點
            m_x2 = x, m_y2 = y;
        } // else if (STATUS_PROC)
        break;
 
    case CV_EVENT_LBUTTONDOWN:
        if (STATUS_WAIT == m_status)
        {
            // 等待狀態(tài)按下鼠標,進入捕捉狀態(tài),固定起點
            m_x1 = x, m_y1 = y;
            m_status = STATUS_PROC;
        } // if (STATUS_WAIT)
        else if (STATUS_PROC == m_status)
        {
            // 捕捉狀態(tài)按下鼠標,捕捉完成,固定終點
            m_x2 = x, m_y2 = y;
            m_status = STATUS_DONE;
        } // else if (STATUS_PROC)
        break;
    } // switch
} // on_mouse()

看完上述內(nèi)容,你們對OpenCV實現(xiàn)摳圖工具的代碼是什么有進一步的了解嗎?如果還想了解更多知識或者相關內(nèi)容,請關注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI