Resize image to square, but keep aspect ratio C ++ opencv

Is there a way to resize images of any shape or size to say [500x500] , but keep the aspect ratio of the image so that the empty space is filled with white / black filler?

So say that the image [2000x1000] , after it has changed to [500x500] , the actual image will be [500x250] , with 125 either side being white / black filler.

Something like that:

Enter

enter image description here

Exit

enter image description here

EDIT

I donโ€™t want to just display the image in a square window, instead of changing the image to this state and then saving it to a file, creating a collection of images of the same size with minimal image distortion.

The only thing I came across when asking a similar question was this post , but its in php .

+8
c ++ image opencv image-resizing
source share
4 answers

Not fully optimized, but you can try the following:

EDIT processes the target size, which is not 500x500 pixels, and terminates it 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; } 
+10
source share

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; } 
+5
source share

Alireza's answer is good, however I changed the code a bit so as not to add 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; } 
+4
source share

You can create another square image you want, then put your image in the middle of the square image. Something like that:

 #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; } 
+1
source share

All Articles