【问题标题】:How to construct an image out of a vector of matrices using opencv如何使用opencv从矩阵向量中构造图像
【发布时间】:2019-04-16 10:48:43
【问题描述】:

我正在将图像拆分为矩形区域,我发现了一些有用的代码可以让我这样做,但是,我无法弄清楚如何操作每个单独的区域并将它们重建回来一起形成一个与原始大小相同的新的完整图像。我对 c++ 和 opencv 都很陌生,所以任何帮助都将不胜感激。

目前,所有矩形都存储在std::vector<cv::Mat> *blocks中。

我想要每个矩形的值并能够操作它们的原因是因为我计划稍后将它们解析为一些输出。

这是将图像分割成矩形的代码:

    if(img.cols % colDivisor == 0 && img.rows % colDivisor == 0){
        for(int y = 0; y < img.cols; y += img.cols/colDivisor){
            for(int x = 0; x < img.rows; x += img.rows/rowDivisor){
                blocks->push_back(img(cv::Rect(y, x, (img.cols / colDivisor), (img.rows / rowDivisor))).clone());
                rectangle(maskImg, cv::Point(y,x), cv::Point(y + (maskImg.cols / colDivisor) - 1, x + (maskImg.rows / rowDivisor) - 1), CV_RGB(255, 0, 0), 1);
                cv::imshow("Image", maskImg);

我可以像这样操作所选图像的 BGR 值:

    std::vector<cv::Mat> m;
    ...
    cv::Mat image2 =m[9]; //Random rect
    std::vector<cv::Mat> channels;
    cv::split(image2, channels);
    cv::Scalar avg1 = cv::mean(channels[0]);
    cv::Scalar avg2 = cv::mean(channels[1]);
    cv::Scalar avg3 = cv::mean(channels[2]);
    std::cout << "Blue channel: " << avg1[0] << std::endl << "Green channel: " << avg2[0] << std::endl << "Red channel: " <<  avg3[0] << std::endl;
    image2.setTo(cv::Scalar(avg1[0], avg2[0], avg3[0]));
    cv::imshow("BGRTEST", image2);

从上面的代码中可以看出,我成功地操作了一个区域,但是,我想遍历每个区域并对其应用平均 BGR 值。

我该怎么做呢?

我尝试使用 c++ 迭代器,如下所示:

for(std::vector<cv::Mat>::iterator it = blocks->begin(); it != blocks->end(); ++it){

}

但是,我不确定如何实现这样的事情。

提前致谢!

【问题讨论】:

    标签: c++ qt opencv


    【解决方案1】:

    假设最初的任务是将图像分割成矩形块并对其应用一些运算符,那么有一个更简单的方法。

    OpenCV 有一个相当方便的感兴趣区域的概念。您可以选择图像的一个区域并将其用作图像。您在那里执行的操作将出现在原始图像中。

    您正在使用感兴趣的区域,但您复制了它,然后计划合并您获得的小图像。这样不仅计算量大,而且代码也比较复杂。

    以下是您可以如何利用感兴趣的区域来发挥自己的优势:

    for(int y = 0; y < img.cols - 30; y += 30) {
        for(int x = 0; x < img.rows - 30; x += 30) {
            cv::Mat roi = img(cv::Rect(y, x, 30, 30));
            std::vector<cv::Mat> channels;
            cv::split(roi, channels);
            cv::Scalar avg1 = cv::mean(channels[0]);
            cv::Scalar avg2 = cv::mean(channels[1]);
            cv::Scalar avg3 = cv::mean(channels[2]);
            roi.setTo(cv::Scalar(avg1[0], avg2[0], avg3[0]));
        }
    }
    

    我已经复制了您的处理并稍微更改了子图像的计算方式。

    【讨论】:

    • 这正是我想要的!可惜我没有注意到 Mat 文档中的 ROI。我已经知道这在计算上很昂贵,所以我真的希望有其他方法。非常感谢!
    猜你喜欢
    • 2017-11-18
    • 2015-07-06
    • 2020-07-01
    • 2017-05-13
    • 2018-04-24
    • 1970-01-01
    • 1970-01-01
    • 2015-09-11
    • 2019-08-04
    相关资源
    最近更新 更多