Show multiple (2,3,4,…) images in the same window in OpenCV

后端 未结 6 1826
臣服心动
臣服心动 2020-12-13 07:11

I want to show 2, 3 or more images in the same window.

My problem is how to put the second, third image just on the right side (above, left or upper) the main image.

相关标签:
6条回答
  • 2020-12-13 07:42

    Try this code (see my comments):

    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 
    
    0 讨论(0)
  • 2020-12-13 07:43

    The GUI included with OpenCV is pretty limited, if you need to do anything complicated, you really should use a GUi framework such as QT or VC++ on windows

    0 讨论(0)
  • 2020-12-13 07:52

    I implemented this very recently. So thought of sharing it. It uses C++ API. The code is self-explanatory (hopefully).

        /**
         * @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;
        }
    

    Here is sample output. Composite image made of multiple images

    0 讨论(0)
  • 2020-12-13 07:54

    The answer depends on which interface you are using (C or C++). General workflow is

    • Create an image (cv::Mat for C++, IplImage* for C) big enough to accomodate your composed image
    • Copy your images into the big image
      • C++: Use the Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange) constructor to get a cv::Mat pointing to a subimage of your original window, then use the copyTo method to copy your small image into the big one
      • C: set a ROI in the big image and copy your small image into it
    • Display your big image
    0 讨论(0)
  • 2020-12-13 07:57

    Or just use:

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

    Mat dst -> | a | b |

    or do it with vector:

    std::vector<cv::Mat> matrices = {
                a, b
        };
    hconcat(matrices, dst);
    
    0 讨论(0)
  • You can find the answer on the OpenCV Wiki:

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

    :-)

    0 讨论(0)
提交回复
热议问题