2017-10-29 13 views
-1

私は画像の回転をしようとしています。ローテーションは問題なく動作しますが、処理中にいくつかのピクセルが削除されているように見え、画像が必要以上に拡大します。画像の回転

あなたはなぜか知っていますか、またはピクセルを紛失したり、大きすぎたりすることなく回転する方法を知っていますか?ここでは、元と結果の画像です:ここで

The Pictures

は、コードは次のとおりです。

#include "opencv2/core/core.hpp" 
#include "opencv2/highgui/highgui.hpp" 

#include <math.h> 
#include <iostream> 
#include <cmath> 

using namespace std; 
using namespace cv; 

int main() { 

    //Initialize Variables 
    int oldWidthImage, oldHeightImage; 
    int newWidthImage, newHeightImage; 
    Mat imageOriginal, resultImage; 

    int delta = 3.141/2; 
    int xPointFrom, xPointTo; 
    int yPointFrom, yPointTo; 

    double x_inputRadians, y_inputRadians; 

    //Load Original Image 
    imageOriginal = imread("C:\\Users\\Wolfz\\Downloads\\Kitty.jpg", CV_LOAD_IMAGE_GRAYSCALE); 
    if (imageOriginal.data && !imageOriginal.empty()) { 
     imshow("Original Image", imageOriginal); 
    } 

    //Inialize the size of the screen to the original size Of image 
    oldWidthImage = 300; 
    oldHeightImage = 300; 

    //Creates new size of image equal to the amount of degrees, to make it possible for the rotated image, to be there 
    if (delta < 3.141/2) { //If under 90 degrees (Radians) 
     newWidthImage = abs((oldWidthImage*cos(delta)) + (oldHeightImage*sin(delta))); 
     newHeightImage = abs((oldHeightImage*sin(delta)) + (oldHeightImage*cos(delta))); 
    } 

    //Get the Point, where to rotate 
    xPointTo = abs(newWidthImage/2 - oldWidthImage/2); 
    xPointFrom = abs(newWidthImage/2 + oldWidthImage/2); 

    yPointTo = abs(newHeightImage/2 - oldHeightImage/2); 
    yPointFrom = abs(newHeightImage/2 + oldHeightImage/2); 

    //Filling in white color in all the possions of the new matrix. 
    resultImage = Mat::ones(Size(abs(newWidthImage), abs(newHeightImage)), CV_8UC1); 


    //Two Foor Loops going through every pixel in the image 
    for (int y_output = 0;y_output < newHeightImage;y_output++) { //Foor loop for y coordinates 
     for (int x_output = 0;x_output < newWidthImage;x_output++) { //Foor loop for x coordinates 

      if (y_output <= oldHeightImage-1) { //This if statement makes sure that it can't go above the original image. Else it would crash 

       //These two statements calculates forward mapping from f(x,y) to g(x',y') 
       x_inputRadians = round(abs(x_output*cos(delta)) + (y_output*sin(delta))); 
       y_inputRadians = round(abs(-x_output*sin(delta)) + (y_output*cos(delta)));    

       if (x_output <= oldWidthImage-1) { 
        //Draw the pixels from image to the big matrix window in the forwarded mapping positions. 
        resultImage.at<uchar>(x_inputRadians, y_inputRadians) = imageOriginal.at<uchar>(x_output, y_output); 
       } 

      } 
     } 
    } 
    //Shows Result image 
    imshow("Result Image", resultImage); 
    waitKey(0); 
} 
+0

の適切な補正を

for (int y = -newHeightImage; y < newHeightImage; y++) { 

このよろしいです回転ですか?それは歪曲のようです。 – DimChtz

+0

実際に歪んで見えます。しかし、私はこのような回転式を使用しているので、回転する必要があります:http://prntscr.com/h3gt64 –

+0

ここで私が見つけることができるいくつかの問題があります: 'int delta'は小数点以下を切り捨てます。それを 'ダブル 'にする。 'pointTo/From'は決して使われません。もし' delta <3.141/2'が成立しなければ、有効な画像幅/高さはありません。 'if(y_output <= oldHeightImage-1)'と 'if(x_output <= oldWidthImage-1) 'というテストは、ループによって直接制御されているので意味をなさない。新しい座標が画像内にあるかどうかを確認してください。回転式の「abs」は意味をなさない。 (btw、私はあなたの変数の名前を直感的に見つけることはできません)。そして見てください[ここ](https://stackoverflow.com/questions/15043152)。 –

答えて

0

あなたは長方形を中心画像を回転したいです。この場合、数式はあなたのリンクショーより少し複雑です。アフィン変換には、ハーフサイズ、回転、シフトバックによるシフトが含まれます。ここ

X_DstX_SrcX_Dst_CYについて同様の結果の半分の幅である、X_Src_Cは、ソース画像の半値幅であり、ソース画像上の点であり、回転画像上の座標です。

X_Src = X_Src_C + (X_Dst - X_Dst_C) * Cos(Angle) + (Y_Dst - Y_Dst_C) * Sin(Angle) 
Y_Src = Y_Dst_C - (X_Dst - X_Src_C) * Sin(Angle) + (Y_Dst - Y_Dst_C) * Cos(Angle) 

あなたは私がnewWidth/Heightのための最も近い整数と正しい設定に丸めると、すべての有効なソースの座標を提供する必要があることを期待if (y_output <= oldHeightImage-1) {

for (int y_output = 0;y_output < newHeightImage;y_output++) { //Foor loop for y coordinates 
    for (int x_output = 0;x_output < newWidthImage;x_output++) { //Foor loop for x coordinates 

     x_input = oldWidthImage/2 + 
        round((x_output - newWidthImage/2) * cos(delta)) + 
         (y_output - newHeightImage/2) *sin(delta))); 
     y_input = oldHeightImage/2 + 
        round(-(x_output - newWidthImage/2) * sin(delta)) + 
         ((y_output - newHeightImage/2) * cos(delta)));    

     resultImage.at<uchar>(x_input, y_input) = imageOriginal.at<uchar>(x_output, y_output); 
    } 
} 

をチェックする必要はありません。そうでない場合は、次のようなソース座標を確認してください。

if (x_input <= oldWidthImage-1) && 
     (x_input >= 0) && 
     (y_input <= oldHeightImage-1) && 
     (y_input >= 0) { 
      resultImage.at... 

P.S.一回のループの前にprecalulate COS(デルタ)と罪(デルタ)、などのループ限度ます:右見て取得した後、あなたが計算を最適化することができますつながる式