skip to Main Content

I have a collection of cv::Mat objects of different sizes. I want to them all to have the same number of columns as the widest matrix in the collection. Matrices that have less columns should be padded to the right with a fixed color. Essentially I want the same functionality as Photoshop’s “Canvas Size…” operation. How should I do that in C++?

cv::resize doesn’t cut it, because it stretches content, instead of padding it. cv::Mat::resize also doesn’t fit the bill because it can only add rows, but not columns.

2

Answers


  1. Chosen as BEST ANSWER

    The trick is to create a new matrix with the desired dimensions and then copy data from the original image into a ROI representing the retained data:

    // Creates a new matrix with size newSize with data copied from source.
    // Source data outside the new size is discarded.
    // If any of the dimensions of newSize is larger than that dimension in source,
    // the extra area is filled with emptyColor.
    cv::Mat resizeCanvas(const cv::Mat& source, cv::Size newSize, cv::Scalar emptyColor) {
        cv::Mat result(newSize, source.type(), emptyColor);
    
        int height = std::min(source.rows, newSize.height);
        int width = std::min(source.cols, newSize.width);
        cv::Rect roi(0, 0, width, height);
    
        auto sourceWindow = source(roi);
        auto targetWindow = result(roi);
        sourceWindow.copyTo(targetWindow);
    
        return result;
    }
    

  2. You can also use copyMakeBorder:

    void resizeCanvas(const cv::Mat& src, cv::Mat& dst, const cv::Size& canvasSize, const cv::Scalar& emptyColor)
    {
        if((canvasSize.height < src.rows) || canvasSize.width < src.cols) {
            // Canvas is smaller than source image
            return;
        }
    
        int bottom = canvasSize.height - src.rows;
        int right = canvasSize.width - src.cols;
    
        cv::copyMakeBorder(src, dst, 0 /*top*/, bottom, 0 /*left*/, right, cv::BORDER_CONSTANT, emptyColor);
    }
    

    Usage:

    cv::Mat3b img = cv::imread("...");
    cv::Mat3b resized;
    resizeCanvas(img, resized, cv::Size(1000, 1000), cv::Scalar(0,0,0,0));
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search