Resize an image to a square but keep aspect ratio c++ opencv

后端 未结 4 509
一向
一向 2021-02-08 05:50

Is there a way of resizing images of any shape or size to say [500x500] but have the image\'s aspect ratio be maintained, levaing the empty space be filled with whi

相关标签:
4条回答
  • 2021-02-08 06:11

    You can create another image of the square size you wish, then put your image in the middle of the square image. Something like this:

    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include "opencv2/imgproc/imgproc.hpp"
    
    int main(int argc, char *argv[])
    {
        // read an image
        cv::Mat image1= cv::imread("/home/hdang/Desktop/colorCode.png");
    
        //resize it
        cv::Size newSize = cv::Size(image1.cols/2,image1.rows/2);
        cv::resize(image1, image1, newSize, 0, 0, cv::INTER_LINEAR);
    
        //create the square container
        int dstWidth = 500;
        int dstHeight = 500;
        cv::Mat dst = cv::Mat(dstHeight, dstWidth, CV_8UC3, cv::Scalar(0,0,0));
    
        //Put the image into the container, roi is the new position
        cv::Rect roi(cv::Rect(0,dst.rows*0.25,image1.cols,image1.rows));
        cv::Mat targetROI = dst(roi);
        image1.copyTo(targetROI);
    
        //View the result
        cv::namedWindow("OpenCV Window");
        cv::imshow("OpenCV Window", dst);
    
        // wait key for 5000 ms
        cv::waitKey(5000);
    
        return 0;
    }
    
    0 讨论(0)
  • 2021-02-08 06:22

    Not fully optimized, but you can try this:

    EDIT handle target size that is not 500x500 pixels and wrapping it up as a function.

    cv::Mat GetSquareImage( const cv::Mat& img, int target_width = 500 )
    {
        int width = img.cols,
           height = img.rows;
    
        cv::Mat square = cv::Mat::zeros( target_width, target_width, img.type() );
    
        int max_dim = ( width >= height ) ? width : height;
        float scale = ( ( float ) target_width ) / max_dim;
        cv::Rect roi;
        if ( width >= height )
        {
            roi.width = target_width;
            roi.x = 0;
            roi.height = height * scale;
            roi.y = ( target_width - roi.height ) / 2;
        }
        else
        {
            roi.y = 0;
            roi.height = target_width;
            roi.width = width * scale;
            roi.x = ( target_width - roi.width ) / 2;
        }
    
        cv::resize( img, square( roi ), roi.size() );
    
        return square;
    }
    
    0 讨论(0)
  • 2021-02-08 06:22

    Alireza's answer is good, however I modified the code slightly so that I don't add the vertical borders when the image fits vertically and I don't add horizontal borders when the image fits horizontally (this is closer to the original request):

    cv::Mat utilites::resizeKeepAspectRatio(const cv::Mat &input, const cv::Size &dstSize, const cv::Scalar &bgcolor)
    {
        cv::Mat output;
    
        // initially no borders
        int top = 0;
        int down = 0;
        int left = 0;
        int right = 0;
        if( h1 <= dstSize.height) 
        {
            // only vertical borders
            top = (dstSize.height - h1) / 2;
            down = top;
            cv::resize( input, output, cv::Size(dstSize.width, h1));
        } 
        else 
        {
            // only horizontal borders
            left = (dstSize.width - w2) / 2;
            right = left;
            cv::resize( input, output, cv::Size(w2, dstSize.height));
        }
    
        return output;
    }
    
    0 讨论(0)
  • 2021-02-08 06:32

    A general approach:

    cv::Mat utilites::resizeKeepAspectRatio(const cv::Mat &input, const cv::Size &dstSize, const cv::Scalar &bgcolor)
    {
        cv::Mat output;
    
        double h1 = dstSize.width * (input.rows/(double)input.cols);
        double w2 = dstSize.height * (input.cols/(double)input.rows);
        if( h1 <= dstSize.height) {
            cv::resize( input, output, cv::Size(dstSize.width, h1));
        } else {
            cv::resize( input, output, cv::Size(w2, dstSize.height));
        }
    
        int top = (dstSize.height-output.rows) / 2;
        int down = (dstSize.height-output.rows+1) / 2;
        int left = (dstSize.width - output.cols) / 2;
        int right = (dstSize.width - output.cols+1) / 2;
    
        cv::copyMakeBorder(output, output, top, down, left, right, cv::BORDER_CONSTANT, bgcolor );
    
        return output;
    }
    
    0 讨论(0)
提交回复
热议问题