視頻標注工具


視頻標注工具

由於實驗室里面需要做CDVA的標准,CDVA(compact descriptor for video analysis),主要是基於CDVS中的緊湊視覺描述子來做視頻分析,之前是緊湊視覺描述子主要應用在圖像檢索領域。需要制作新的數據集,對視頻幀進行標注,所以根據網上一個博主的標注工具進行了一定的修改,實現的功能是在每一幀中將需要標注的區域用鼠標選取4個點,順序是順時針。因為四邊形的范圍更廣,之前的一些人直接標注了矩形,但是在一些仿射變換中,往往矩形的定位效果不好,矩形定位應該比較適合於人臉定位和行人定位之中。

這些代碼都是基於openCV的,因此在工程配置的時候需要天機opencv的庫路徑和頭文件路徑。
這里簡單的介紹一下這個工具的用法

  • 首先運行這個應用程序可以看到一個黑框和一個Video窗口
  • 選取需要標注的區域,按照順時針,畫出4個點(此工具的寫的時候默認是每幀圖像畫一個,不考慮多個情況,如果你要標注多個,就可以添加一個數組存取每個四邊形的區域
  • 在畫的時候若是點錯了地方需求進一步修正則按 'z'即可,按下‘z’可以回退一個點,若畫完4個點感覺還是不滿意,也可以直接按下'c'全部清除
  • 當確定矩形區域之后,按下‘n’,就會將這些數據寫入到指定的txt文件中,同時將進入下一幀
  • 由於視頻中連續幀的變化不好,特別是鏡頭停止的時候,因此,為了避免重復畫目標區域,上一幀的四邊形坐標會自動的畫在下一幀中,若需要重新畫,按下‘c’,即可,若不需要重新畫,按下'n'即會寫入文件,同時繼續下一幀,如此往復

在寫入的txt文件中,一行代表一幀中的數據,第一個數為幀數,后4個數,分別是畫矩形時依次點入的4個坐標值。
你可以根據自己的需求,修改這份代碼,希望對大家能有所幫助。

/********************************************************************
    created:	2015/04/18
    created:	18:4:2015   17:24
    filename: 	D:\WorkSpace\VS_Projects\VideoLabel\VideoLabel_Quadrilateral\video_label_quadrilateral.cpp
    file path:	D:\WorkSpace\VS_Projects\VideoLabel\VideoLabel_Quadrilateral
    file base:	video_label_quadrilateral
    file ext:	cpp
    author:		Yihang Lou
    purpose:	draw the quadrilateral labels in the frame captured from video
*********************************************************************/
#include "opencv2/opencv.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
using namespace cv;

// Global variables

Mat img_original, img_drawing;
Point quad [4];
//the value of pointNum is between 0~4
static int pointNum = 0;
/*************************************************
// Method: help
// Description: describe the usage
// Author: Yihang Lou
// Date: 2015/04/18
// Returns: void
// History:
*************************************************/
static void help()
{
    cout << "This program designed for labeling video \n"
            "Only if you press the 'n' the present quadrilateral data will be written into txt file\n";


        cout << "Hot keys: \n"
        "\tESC - quit the program\n"
        "\tn - next frame of the video\n"
        "\tz - undo the last label point \n"
        "\tc - clear all the labels\n"
        << endl;
}
/*************************************************
// Method: drawQuadri
// Description: 
// Author: Yihang Lou 
// Date: 2015/04/18
// Returns: void
// Parameter: quad the point of Point array
// History:
*************************************************/
static void drawQuadri (Point * quad) {
    for(int i = 0; i < 4; i++)
    {
        line(img_drawing,quad[i],quad[(i+1)%4],Scalar(0,255,0),1,8,0);
    }
}


/*************************************************
// Method: onMouse
// Description: do the actions after onMouse event is called
// Author: Yihang Lou 
// Date: 2015/04/18
// Returns: void
// Parameter: event
// Parameter: x Mouse's coordinate
// Parameter: y 
// History:
*************************************************/
static void onMouse(int event, int x, int y, int, void*)
{


    switch (event)
    {
    case CV_EVENT_LBUTTONDOWN:
        quad[pointNum%4].x = x;
        quad[pointNum%4].y = y;
        cout<<"x = "<<x<<" y = "<<y<<endl;
        pointNum++;

        break;
    case CV_EVENT_LBUTTONUP:
        //finish drawing the rect (use color green for finish)

        circle(img_drawing,cvPoint(x,y),1,Scalar(0, 255, 0),1,8,0);

        if(pointNum == 4)
        {
            pointNum = 0;

            cout<<"draw quadri line"<<endl;
            drawQuadri(quad);
        }

        break;
    }

    imshow("Video", img_drawing);
    return;
}

/*************************************************
// Method: isempty
// Description: check the quad is empty
// Author: Yihang Lou 
// Date: 2015/04/18
// Returns: int
// Parameter: quad
// History:
*************************************************/
int isempty(Point * quad)
{
    for (int i = 0 ; i < 4; i++)
    {
        if (quad[i].x !=0 || quad[i].y !=0 )
        {
            return 0;
        }
    }
    return 1;
}
int main(){
    namedWindow("Video");
    ofstream outfile("1.txt");
    help();
    VideoCapture capture("1.avi");
    capture >> img_original;
    img_original.copyTo(img_drawing);
    imshow("Video", img_original);
    setMouseCallback("Video", onMouse, 0);
    int frame_counter = 0;
    while (1){
        int c = waitKey(0);
        if ((c & 255) == 27)
        {
            cout << "Exiting ...\n";
            break;
        }
        switch ((char)c)
        {
        case 'n':
            //read the next frame
            ++frame_counter;
            capture >> img_original;
            if (img_original.empty()){
                cout << "\nVideo Finished!" << endl;
                return 0;
            }

            img_original.copyTo(img_drawing);

            if (!isempty(quad))
            {
                drawQuadri(quad);

                outfile << frame_counter << " " << quad[0].x << " "<< quad[0].y << " " 
                    << quad[1].x << " "<< quad[1].y << " "
                    << quad[2].x << " "<< quad[2].y << " "
                    << quad[3].x << " "<< quad[3].y << " "<<endl;
            }

            break;
        case 'z':
            //undo the latest labeling point
            if(pointNum == 0)
            {
                cout<<"if you want to clear the existent quad please press 'c'"<<endl;
                break;
            }
            pointNum--;
            quad[pointNum].x=0;
            quad[pointNum].y=0;
            img_original.copyTo(img_drawing);
            for(int i = 0 ; i < pointNum; i++)		
            {
                circle(img_drawing,quad[i],1,Scalar(0, 255, 0),1,8,0);
            }

            break;
        case 'c':
            //clear quad array
            memset(quad,0,4*sizeof(Point));
            img_original.copyTo(img_drawing);
        }
        imshow("Video", img_drawing);
    }

    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM