web-dev-qa-db-ja.com

画像のサイズを正方形に変更しますが、アスペクト比はc ++ opencvのままにします

[500x500]と言うように任意の形状またはサイズの画像のサイズを変更する方法はありますが、画像のアスペクト比を維持し、空のスペースを白/黒のフィラーで埋めますか?

したがって、画像が[2000x1000]であるとすると、[500x500]にサイズ変更された後、実際の画像自体は[500x250]になり、125の両側が白/黒のフィラーになります。

このようなもの:

入力

enter image description here

出力

enter image description here

[〜#〜]編集[〜#〜]

単純に正方形のウィンドウに画像を表示するのではなく、画像をその状態に変更してからファイルに保存し、画像の歪みを最小限に抑えて同じサイズの画像のコレクションを作成します。

私が同じような質問をするのに出くわした唯一のことは この投稿 でしたが、それはphpにあります。

10
MLMLTL

完全には最適化されていませんが、これを試すことができます:

[〜#〜] edit [〜#〜]500x500ピクセルではないターゲットサイズを処理し、関数としてラップします。

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;
}
14
Rosa Gronchi

一般的なアプローチ:

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;
}
7
alireza

Alirezaの答えは良いですが、画像が垂直に収まるときに垂直の境界線を追加せず、画像が水平に収まるときに水平の境界線を追加しないようにコードを少し変更しました(これは元のリクエストに近いです):

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;
}
3
Dragan Ostojić

希望する正方形のサイズの別の画像を作成してから、その画像を正方形の画像の中央に配置できます。このようなもの:

#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
Ha Dang