【问题标题】:Cropping an triangle from captured frame - OpenCV and C++从捕获的帧中裁剪三角形 - OpenCV 和 C++
【发布时间】:2018-10-13 13:52:49
【问题描述】:

我有一个要从中捕获帧的视频文件。我想从捕获的帧中裁剪一个三角形并显示它,但我的程序只显示一个源帧。

这是我的代码:

cv::Mat Detector::cropRegionOfInterest(cv::Mat& frame)
{
    cv::Point corners[1][3];
    corners[0][0] = cv::Point(0, frameHeight);
    corners[0][1] = cv::Point(frameWidth, frameHeight);
    corners[0][2] = cv::Point(frameWidth / 2, frameHeight / 2);

    const cv::Point* cornerList[1] = { corners[0] };

    int numPoints = 3;
    int numPolygons = 1;

    cv::Mat mask(frame.size(), CV_8UC1, cv::Scalar(0, 0, 0));
    cv::fillPoly(mask, cornerList, &numPoints, numPolygons, cv::Scalar(255, 255, 255), 8);

    cv::Mat result(frame.size(), CV_8UC3);
    cv::bitwise_and(frame, mask, result);

    return result;
}

我希望它显示裁剪的三角形,而不是显示源框架。

【问题讨论】:

    标签: c++ opencv computer-vision crop


    【解决方案1】:

    由于您使用CV_8UC3 作为result 的类型,我假设(如果不是这种情况,请参阅答案末尾的编辑)输入图像frame 也有@987654325 @频道。在这种情况下,您甚至可以看到未裁剪的图像,这让我有点惊讶,因为运行您的代码只会在我的机器上调用 bitwise_and 时引发异常:

    OpenCV(3.4.1) Error: Sizes of input arguments do not match
    

    documentation,在我看来,您不能混合不同的输入和掩码类型。一个快速而肮脏的解决方案是将输入图像拆分为三个通道的向量,为每个通道调用bitwise_and,然后将它们合并回来。下面的代码对我有用:

    #include <stdio.h>
    #include <opencv2/opencv.hpp>
    
    using namespace cv;
    
    
    cv::Mat cropRegionOfInterest(cv::Mat& frame)
    {
    
        const int frameWidth=frame.cols-1;
        const int frameHeight=frame.rows-1;
        cv::Point corners[1][3];
        corners[0][0] = cv::Point(0, frameHeight);
        corners[0][1] = cv::Point(frameWidth, frameHeight);
        corners[0][2] = cv::Point(frameWidth / 2, frameHeight / 2);
    
        const cv::Point* cornerList[1] = { corners[0] }; 
    
        int numPoints = 3; 
        int numPolygons = 1; 
    
        cv::Mat mask(frame.rows,frame.cols, CV_8UC1, cv::Scalar(0, 0, 0));
        cv::fillPoly(mask, cornerList, &numPoints, numPolygons, cv::Scalar(255, 255, 255), 8);
    
        std::vector<cv::Mat> src_channels;
        std::vector<cv::Mat> result_channels;
        cv::split(frame,src_channels);
    
        for(int idx=0;idx<3;++idx)
        {  
          result_channels.emplace_back(frame.rows,frame.cols,CV_8UC1);
          cv::bitwise_and(src_channels[idx], mask,result_channels[idx]);
    
        }  
        cv::Mat result;
        cv::merge(result_channels,result);
        return result;
    }
    
    
    int main(int argc, char** argv )
    {
        if ( argc != 2 )
        {  
            printf("usage: DisplayImage.out <Image_Path>\n");
            return -1;
        }  
    
        Mat image;
        image = imread( argv[1], 1 ); 
    
        if ( !image.data )
        {  
            printf("No image data \n");
            return -1;
        }  
    
        cv::Mat cropped=cropRegionOfInterest(image);
    
        namedWindow("cropped Image", WINDOW_AUTOSIZE ); 
        imshow("cropped Image", cropped);
    
        waitKey(0);
    
        return 0; 
    }
    

    编辑:从您的 cmets 看来,frame 实际上是灰度的。在这种情况下,别管上面的所有代码,只需将 cv::Mat result(frame.size(), CV_8UC3); 更改为

    cv::Mat result(frame.rows,frame.cols,CV_8UC1);
    

    在您的原始代码中。

    【讨论】:

    • @msk 啊,这很奇怪。在哪一行?
    • @msk 另外,你是如何运行它的?你用的是哪个opencv版本?尝试添加尽可能多的信息。说段错误本身并不是很有帮助。这也适用于您的问题,正如您所见,我不得不猜测您的输入帧的类型;)
    • 我认为循环的第一次迭代完成后会抛出段错误。
    • 我使用的是 3.4.1 版本,帧是从 mp4 视频文件中捕获的
    • @msk 嗯,这很奇怪,因为它在我的机器上运行得很好。您可以在命令行中使用任意 RGB 图像运行我的代码吗?如果它有效,那么我认为问题可能来自frame.type()...
    猜你喜欢
    • 2016-02-11
    • 2013-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-29
    • 2018-08-22
    • 2015-01-04
    • 1970-01-01
    相关资源
    最近更新 更多