如何在Android中使用Opencv在非平稳背景下检测对象的存在?

时间:2019-03-28 13:42:37

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

我正在开发一个应用程序来处理帧,并使用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进行背景减法。

它们都不起作用,因为背景也在移动,因此这些逻辑根本不健全。

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

希望大家能引导我找到一个好的解决方案,并在此先感谢您。

1 个答案:

答案 0 :(得分:1)

面对这个问题,我使用了光流

您可以使用calcOpticalFlowFarneback计算每帧的光通量。

然后,对于图像的每个像素,您将获得一个由2个分量组成的矩阵(在x方向和y方向上渐变)。

我为每个点atan2(flow_y,flow_x)计算并存储在vector<Point2f>中。

然后,仅使用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;
}