【问题标题】:Show multiple (2,3,4,…) images in the same window in OpenCV在 OpenCV 的同一窗口中显示多个 (2,3,4,…) 图像
【发布时间】:2011-07-02 16:10:36
【问题描述】:

我想在同一个窗口中显示 2、3 或更多图像。

我的问题是如何将第二、第三张图片放在主图片的右侧(上方、左侧或上方)。

我想使用 OpenCV 创建类似的东西。

---------------
|      |      |
|      |      |
---------------
|    |        |
|    |        |
---------------

提前致谢 豪尔赫

【问题讨论】:

    标签: image opencv window


    【解决方案1】:

    答案取决于您使用的接口(C 或 C++)。一般工作流程是

    • 创建一个足以容纳您合成的图像的图像(cv::Mat 用于 C++,IplImage* 用于 C)
    • 将图像复制到大图像中
      • C++:使用Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)构造函数得到一个cv::Mat指向原始窗口的子图像,然后使用copyTo方法将小图像复制到大图像中
      • C:在大图像中设置 ROI,然后将小图像复制到其中
    • 显示您的大图

    【讨论】:

    • 好的。谢谢你的主意。 ROI 在 OpenCV 中非常重要。
    【解决方案2】:

    OpenCV 附带的 GUI 非常有限,如果你需要做一些复杂的事情,你真的应该在 windows 上使用 QT 或 VC++ 等 GUI 框架

    【讨论】:

    • 我使用 MAC。但现在我只想使用 OpenCV 框架。我知道将来需要使用外部框架来获得更多选择。谢谢你的回答。
    【解决方案3】:

    您可以在 OpenCV Wiki 上找到答案:

    https://github.com/opencv/opencv/wiki/DisplayManyImages

    :-)

    【讨论】:

    【解决方案4】:

    我最近实现了这一点。于是想到分享。 它使用 C++ API。该代码是不言自明的(希望如此)。

        /**
         * @brief makeCanvas Makes composite image from the given images
         * @param vecMat Vector of Images.
         * @param windowHeight The height of the new composite image to be formed.
         * @param nRows Number of rows of images. (Number of columns will be calculated
         *              depending on the value of total number of images).
         * @return new composite image.
         */
        cv::Mat makeCanvas(std::vector<cv::Mat>& vecMat, int windowHeight, int nRows) {
                int N = vecMat.size();
                nRows  = nRows > N ? N : nRows; 
                int edgeThickness = 10;
                int imagesPerRow = ceil(double(N) / nRows);
                int resizeHeight = floor(2.0 * ((floor(double(windowHeight - edgeThickness) / nRows)) / 2.0)) - edgeThickness;
                int maxRowLength = 0;
    
                std::vector<int> resizeWidth;
                for (int i = 0; i < N;) {
                        int thisRowLen = 0;
                        for (int k = 0; k < imagesPerRow; k++) {
                                double aspectRatio = double(vecMat[i].cols) / vecMat[i].rows;
                                int temp = int( ceil(resizeHeight * aspectRatio));
                                resizeWidth.push_back(temp);
                                thisRowLen += temp;
                                if (++i == N) break;
                        }
                        if ((thisRowLen + edgeThickness * (imagesPerRow + 1)) > maxRowLength) {
                                maxRowLength = thisRowLen + edgeThickness * (imagesPerRow + 1);
                        }
                }
                int windowWidth = maxRowLength;
                cv::Mat canvasImage(windowHeight, windowWidth, CV_8UC3, Scalar(0, 0, 0));
    
                for (int k = 0, i = 0; i < nRows; i++) {
                        int y = i * resizeHeight + (i + 1) * edgeThickness;
                        int x_end = edgeThickness;
                        for (int j = 0; j < imagesPerRow && k < N; k++, j++) {
                                int x = x_end;
                                cv::Rect roi(x, y, resizeWidth[k], resizeHeight);
                                cv::Size s = canvasImage(roi).size();
                                // change the number of channels to three
                                cv::Mat target_ROI(s, CV_8UC3);
                                if (vecMat[k].channels() != canvasImage.channels()) {
                                    if (vecMat[k].channels() == 1) {
                                        cv::cvtColor(vecMat[k], target_ROI, CV_GRAY2BGR);
                                    }
                                } else {             
                                    vecMat[k].copyTo(target_ROI);
                                }
                                cv::resize(target_ROI, target_ROI, s);
                                if (target_ROI.type() != canvasImage.type()) {
                                    target_ROI.convertTo(target_ROI, canvasImage.type());
                                }
                                target_ROI.copyTo(canvasImage(roi));
                                x_end += resizeWidth[k] + edgeThickness;
                        }
                }
                return canvasImage;
        }
    

    这是示例输出。

    【讨论】:

    • 我们如何改变它以显示灰度图像?因为我试过了,它只适用于彩色图像。
    • @Maystro : 我已经修改了代码以支持灰度和彩色图像。
    • 我猜这是最好的解决方案。无论如何,我不得不对其进行一些修改,因为您忘记将 vecMat[k] 数据复制到 target_ROI Mat 以防彩色图像。
    【解决方案5】:

    或者直接使用:

    Mat a, Mat b, Mat dst // a,b loaded
    
    cv::hconcat(a, b, dst) // horizontal
    cv::vconcat(a, b, dst) // vertical
    

    垫 dst -> |一个 |乙 |

    或者用矢量来做:

    std::vector<cv::Mat> matrices = {
                a, b
        };
    hconcat(matrices, dst);
    

    【讨论】:

      【解决方案6】:

      试试这个代码(见我的 cmets):

      Mat img = imread("lena.JPG");
      
      CV::Mat chann[3], all; //  creating 
      
      split(img, chann); // split an image into their color channel and n keep them inside
      
      a 3 element array called chann
      
      imshow("ppl", img);
      
      hconcat(chann, 3, all); //  joining the images together in a horizontal manner, the 
      
      array, number of array, and the destination
      
      imshow("B :: G :: R",all);     // this just the little help i could provide 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-19
        • 1970-01-01
        • 1970-01-01
        • 2015-08-01
        • 1970-01-01
        • 1970-01-01
        • 2012-02-09
        相关资源
        最近更新 更多