RayShick 2020-01-13 10:30 采纳率: 0%
浏览 453

opencv实现边缘梯度直方图+meanshift实现框选物体跟踪,代码出错,不知道错在哪里?

#include<iostream>
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<ctype.h>
using namespace std;
using namespace cv;

Mat image;         //当前帧图像 
Mat imageCopy; //用于拷贝的当前帧图像  
Mat rectImage;   //子图像
Point beginPoint; //矩形框起点  
Point endPoint;  //矩形框终点  
bool leftButtonDownFlag = false; //左键单击后视频暂停播放的标志位  
int frameCount = 0; //帧数统计 
int trackCount = 0;  //等于1时初始化直方图
void onMouse(int event, int x, int y, int flags, void* ustc); //鼠标回调函数  

int main(int argc, char* argv[]) {

    VideoCapture capture("1.AVI");
    //VideoCapture capture(0);
    int capture_fps = capture.get(CV_CAP_PROP_FPS); //获取视频帧率 
    int capture_count = capture.get(CV_CAP_PROP_FRAME_COUNT);
    int capture_width = capture.get(CV_CAP_PROP_FRAME_WIDTH);
    int capture_height = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
    cout << "视频帧率:" << capture_fps << endl;
    cout << "视频帧数:" << capture_count << endl;
    cout << "视频宽度:" << capture_width << endl;
    cout << "视频高度:" << capture_height << endl;
    int pauseTime = 1000 / capture_fps; //两幅画面中间间隔  

    namedWindow("Video");
    setMouseCallback("Video", onMouse);//函数setMousecallback用于鼠标在图上做标记等作用
    int hbinNum = 16;//每一维上直方图的个数,如果是一维直方图,就是竖条(bin)的个数
    float hranges[] = { 40, 250 };//每一维数值的取值范围数组
    const float* phranges = hranges;//const修饰phranges指针,指针phranges的指向可以修改,但是phranges指向的值不可以改;指针phranges指向的是hranges的首地址
    bool backprojectMode = false;

    namedWindow("Video", 0);
    capture >> image;
    int rows = image.rows;
    int cols = image.cols;
    Mat image1 = image.clone();
    Mat dst, edge, gray;//定义canny边缘检测所需的变量
    Mat abs_grad_x, abs_grad_y;//定义sobel算子求方向梯度所需的变量
    Mat grad_x(rows, cols, CV_8UC1, Scalar::all(0));//定义sobel算子求方向梯度所需的变量
    Mat grad_y(rows, cols, CV_8UC1, Scalar::all(0));//定义sobel算子求方向梯度所需的变量

    Mat theta(rows, cols, CV_32FC1, Scalar::all(0));
    Mat gradient(rows, cols, CV_32FC1, Scalar::all(0));//梯度矩阵
    Mat angle(rows, cols, CV_32FC1, Scalar::all(0));//梯度方向角度
    Mat  mask, hist, histImg = Mat::zeros(image.size(), image.type()), backproj;//初始化histImg存储直方图数据,使其规格与捕获的image相同
    Rect trackWindow;//定义一个捕捉矩形窗口

    //**********************读取视频********************************
    while (true) {
        if (!leftButtonDownFlag) //鼠标左键按下绘制矩形时,视频暂停播放  
        {
            capture >> image;//读取当前帧
            frameCount++;   //帧数增加,视频向前增加 
        }
        if (!image.data || waitKey(pauseTime + 30) == 27)  //当当前帧的数据为空或两帧画面的时间间隔不满足规定的数值时,退出播放
        {
            break;
        }


        //***************camshiftdemo代码的脉络分析********************
        //提取边缘梯度大小与幅值
        if (trackCount > 0) {
            dst.create(image1.size(), image1.type()); 
            dst = Scalar::all(0);
            cvtColor(image1, gray, COLOR_BGR2GRAY);
            GaussianBlur(gray, edge, Size(3, 3), 0, 0);
            Canny(edge, edge, 3, 9, 3);//canny算子获得边缘图
            Sobel(gray, grad_x, CV_16S,1, 0, 3, 1, 1);//求X方向的梯度
            Sobel(gray, grad_y, CV_16S,0, 1, 3, 1, 1);//求Y方向的梯度
            cartToPolar(grad_x, grad_y, gradient, angle);//计算梯度方向与梯度幅值 
            convertScaleAbs(grad_x, grad_x);
            convertScaleAbs(grad_y, grad_y);

            //绘制直方图
            if (trackCount == 1) {
                histImg = Scalar::all(0);
                Mat roi(angle, Rect(beginPoint, endPoint)), maskroi(mask, Rect(beginPoint, endPoint));
                calcHist(&roi, 1, 0, maskroi, hist, 1, &hbinNum, &phranges);//掩膜maskroi是用来确定输入图像的哪些像素被计数;mask也设置ROI, 是要让hue中截取出来放在mask中的 区域大小位置都和hue中一致, 不要改变原来的位置这点很有用。
                normalize(hist, hist, 0, 255, CV_MINMAX);
                trackCount++;
                trackWindow = Rect(beginPoint, endPoint);
            }


            calcBackProject(&angle, 1, 0, hist, backproj, &phranges);//直方图反向投影
            backproj &= mask;
            meanShift(backproj, trackWindow, TermCriteria(CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1));//CamshiftDemo

            //***画出跟踪区域的位置
            if (backprojectMode) {
                cvtColor(backproj, image, CV_GRAY2BGR);
            }
            rectangle(image, Point(trackWindow.x, trackWindow.y), Point(trackWindow.x + trackWindow.width, trackWindow.y + trackWindow.height), Scalar(0, 0, 255), 1, CV_AA);//画跟踪矩形框
            trackCount++;

            //  writer << image;
        }
        imshow("Video", image);

    }
    waitKey(0);
    return 0;
}

//鼠标回调函数    
void onMouse(int event, int x, int y, int flags, void *ustc)
{
    if (event == CV_EVENT_LBUTTONDOWN)
    {
        leftButtonDownFlag = true; //标志位  
        beginPoint = Point(x, y);  //设置左键按下点的矩形起点  
        endPoint = beginPoint;
    }
    if (event == CV_EVENT_MOUSEMOVE && leftButtonDownFlag)
    {
        imageCopy = image.clone();
        endPoint = Point(x, y);
        if (beginPoint != endPoint)
        {
            //在复制的图像上绘制矩形  
            rectangle(imageCopy, beginPoint, endPoint, Scalar(0, 0, 255), 2);
        }
        imshow("Video", imageCopy);
    }
    if (event == CV_EVENT_LBUTTONUP)
    {
        leftButtonDownFlag = false;
        Mat subImage = image(Rect(beginPoint, endPoint)); //子图像  
        rectImage = subImage.clone();
        trackCount = 1;
        //imshow("Sub Image", rectImage);
    }
}
  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
    • ¥50 有数据,怎么用matlab求全要素生产率
    • ¥15 TI的insta-spin例程
    • ¥15 完成下列问题完成下列问题
    • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
    • ¥15 YoloV5 第三方库的版本对照问题
    • ¥15 请完成下列相关问题!
    • ¥15 drone 推送镜像时候 purge: true 推送完毕后没有删除对应的镜像,手动拷贝到服务器执行结果正确在样才能让指令自动执行成功删除对应镜像,如何解决?
    • ¥15 求daily translation(DT)偏差订正方法的代码
    • ¥15 js调用html页面需要隐藏某个按钮