【问题标题】:How to detect the presence of an object in a non-stationary background using Opencv in Android?如何在Android中使用Opencv检测非静止背景中物体的存在?
【发布时间】:2019-08-19 07:32:20
【问题描述】:

我正在开发一个应用程序来处理帧,并在 Android 中使用 Opencv 实时进行分割和图像匹配。

主要问题是,只有当相机帧中有要处理的对象并且背景不固定时,我才需要开始此图像处理,这使我的任务变得更加困难。

我尝试了许多解决方案,例如使用absdiff 进行运动检测,这是代码

    imgSource = inputFrame.rgba().t();
    Core.transpose(imgSource, imgSource);

    //imgSource.convertTo(enhancedMat, imgSource.type(), 1.3);



    gray = imgSource;
    Imgproc.cvtColor(imgSource, gray, Imgproc.COLOR_BGR2GRAY);
    Imgproc.GaussianBlur(gray, gray, new Size(25, 25), 5);
    if (firstframe == null) {
        firstframe = gray;
    }
    Core.absdiff(firstframe, gray, frameDelta);
    Imgproc.threshold(frameDelta, frameDelta, 25, 255, Imgproc.THRESH_BINARY);
    for (int i =0 ; i <2 ; i++)
        Imgproc.dilate(frameDelta, frameDelta, Imgproc.getStructuringElement(Imgproc.THRESH_BINARY, new Size(3, 3)));

    Imgproc.findContours(frameDelta, abs_contours, abs_hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
    for (int idx = 0; idx < abs_contours.size(); idx++) {

        double a = Imgproc.contourArea(abs_contours.get(idx));  //Find the area of contour

        if (a < 10000) {

            continue;
        }

        Rect rect = Imgproc.boundingRect(abs_contours.get(idx));
        Imgproc.rectangle(imgSource, rect.tl(), rect.br(), new Scalar(0, 255, 0), 2);
    }

我也尝试使用这个 Opencv 方法createBackgroundSubtractorMOG2 进行背景减法。

它们都不起作用,因为背景也在移动,所以这些逻辑根本不可靠。

对于这类问题有什么我必须遵循的方法或任何解决方案吗?

我希望你们能指导我找到一个好的解决方案,并提前谢谢你们。

【问题讨论】:

    标签: java android image-processing computer-vision opencv4android


    【解决方案1】:

    为了解决这个问题,我使用了光流

    您可以使用calcOpticalFlowFarneback 计算每一帧上的光流。

    然后,您会为图像的每个像素获得一个包含 2 个分量(x 方向和 y 方向的梯度)的矩阵。

    我计算了每个点 atan2(flow_y,flow_x) 并将其存储在 vector&lt;Point2f&gt; 中。

    然后,只需使用 kmeans 和 2 个标签进行聚类。 (将背景与序列中的前景移动对象区分开来)。

    kmeans 返回的矩阵为您提供标签。

    希望对你有帮助!

    编辑:

    我一直在使用 OpenCV C++,但这是我的代码

    int calculateOptFlow(Mat prev_frame, Mat frame, Mat& output) 
    {
        Mat flow;
    
        //the algorithm uses gray images
        cvtColor(frame,frame,CV_BGR2GRAY);
        cvtColor(prev_frame,prev_frame,CV_BGR2GRAY);
    
        calcOpticalFlowFarneback(prev_frame, frame, flow,0.4, 1, 12, 2, 8, 1.2, 0);
    
        Mat angle(flow.rows,flow.cols,CV_32FC1);
        Mat dst(flow.rows,flow.cols,CV_32FC1);
        vector<Point2f> samples(flow.rows*flow.cols);
    
        int n=0;
        for(int y=0;y<flow.rows;y++)
        {
            for(int x=0;x<flow.cols ; x++)
            {
    
                angle.at<float>(y,x) = (atan2(flow.at<Point2f>(y,x).y,flow.at<Point2f>(y,x).x));
                samples[n++] =  flow.at<Point2f>(y,x);
            }
        }
    
        // split into 2 clusters : background and foreground
        Mat labels,centers;
        kmeans(samples,2,labels,TermCriteria(TermCriteria::EPS+TermCriteria::COUNT,10,1.0),3,KMEANS_PP_CENTERS,centers);
    
        // create a B&W matrix from the labels
        for(int i=0;i<(int)samples.size();i++)
        {
            int row = static_cast<int>(i/dst.cols);
            int col = i%dst.cols;
            if(labels.at<int>(i) == 1)
            {
                dst.at<float>(row,col) = 255;
            }
            else
            {
                dst.at<float>(row,col) = 0;
            }
        }
    
        //conversion for the use of findContours afterwards
        dst.convertTo(output,CV_8UC1);
    
        return 1;
    }
    

    【讨论】:

    • 这是一个很好的解决方案,但我是新手,你能提供一个在android中使用光流的例子吗?
    • 甚至是您在答案中提供的步骤的 c++ 示例
    • 你能告诉我那个变量flow是什么吗?它只是output 的副本吗?
    • 是的,对不起,我将 2 个函数连接到 1 个函数中并忘记了这个变量。 flow 是 calcOpticalFlowFarneback 的输出。我编辑了我的代码!
    猜你喜欢
    • 1970-01-01
    • 2022-10-26
    • 2015-10-01
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    相关资源
    最近更新 更多