简体   繁体   English

如何使用OpenCV将c ++代码转换为Python以自​​动旋转图像?

[英]How to convert the c++ code to Python for automatic image rotation using OpenCV?

I want to do the following: 我要执行以下操作:

  1. Rotate the Incoming Image to align it perfectly with the Template Image . 旋转Incoming Image以使其与Template Image完美对齐。
  2. Use cv2.substrate() to compare the two aligned images & print out the difference. 使用cv2.substrate()比较两个对齐的图像并打印出差异。

I already have the Python code to do the image comparison: 我已经有了Python代码来进行图像比较:

import cv2
import numpy as np

image1 = cv2.imread('letter f5.png') 
image2 = cv2.imread('letter f.png') 

difference = cv2.subtract(image1, image2)

result = np.any(difference) 

if result is True:
    print ("The images are the same")
else:
    cv2.imshow("result.jpg", difference)
    print ("the images are different")

The image comparison works well if the two images are aligned. 如果两个图像对齐,则图像比较效果很好。 If the Incoming Image is off by 90 degree clockwise, the image comparison won't work. 如果“ Incoming Image沿顺时针方向偏移了90度,则图像比较将无法进行。

So, how can I rotate this image: 因此,如何旋转此图像:

顺时针旋转90度

To this: 对此:

对齐的传入图像

So that I'll be able to compare it with Template Image . 这样我就可以将其与Template Image进行比较。

I have this c++ code: 我有这个C ++代码:

#include <stdio.h>
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#define PI 3.14159265

using namespace cv;
using namespace std;


void rotate(cv::Mat& src, double angle, cv::Mat& dst)
{
    int len = std::max(src.cols, src.rows);
     cv::Point2f pt(len/2., len/2.);
     cv::Mat r = cv::getRotationMatrix2D(pt, angle, 1.0);

     cv::warpAffine(src, dst, r, cv::Size(len, len));
}



float angleBetween(const Point &v1, const Point &v2)
{
    float len1 = sqrt(v1.x * v1.x + v1.y * v1.y);
    float len2 = sqrt(v2.x * v2.x + v2.y * v2.y);

    float dot = v1.x * v2.x + v1.y * v2.y;

    float a = dot / (len1 * len2);

    if (a >= 1.0)
        return 0.0;
    else if (a <= -1.0)
        return PI;
    else{
        int degree;
        degree = acos(a)*180/PI;
        return degree;
        };
}



int main()
{

    Mat char1 = imread( "/Users/Rodrane/Documents/XCODE/OpenCV/mkedenemeleri/anarev/rotated.jpg",CV_LOAD_IMAGE_GRAYSCALE );

    Mat image = imread("/Users/Rodrane/Documents/XCODE/OpenCV/mkedenemeleri/anarev/gain2000_crop.jpg", CV_LOAD_IMAGE_GRAYSCALE );




    if( !char1.data )
    {
        std::cout<< "Error reading object " << std::endl;
        return -1;
    }

    GaussianBlur( char1, char1, Size(3, 3), 2, 2 );
    GaussianBlur( image, image, Size(3, 3), 2, 2 );
    adaptiveThreshold(char1,char1,255,CV_ADAPTIVE_THRESH_MEAN_C,CV_THRESH_BINARY,9,14);
    adaptiveThreshold(image,image,255,CV_ADAPTIVE_THRESH_MEAN_C,CV_THRESH_BINARY,9,14);

    //Detect the keypoints using SURF Detector
    int minHessian = 200;

    SurfFeatureDetector detector( minHessian );
    std::vector<KeyPoint> kp_object;

    detector.detect( char1, kp_object );

    //Calculate descriptors (feature vectors)
    SurfDescriptorExtractor extractor;
    Mat des_object;

    extractor.compute( char1, kp_object, des_object );

    FlannBasedMatcher matcher;


    namedWindow("Good Matches");

    std::vector<Point2f> obj_corners(4);

    //Get the corners from the object
    obj_corners[0] = cvPoint(0,0);
    obj_corners[1] = cvPoint( char1.cols, 0 );
    obj_corners[2] = cvPoint( char1.cols, char1.rows );
    obj_corners[3] = cvPoint( 0, char1.rows );



    Mat frame;




    Mat des_image, img_matches;
    std::vector<KeyPoint> kp_image;
    std::vector<vector<DMatch > > matches;
    std::vector<DMatch > good_matches;
    std::vector<Point2f> obj;
    std::vector<Point2f> scene;
    std::vector<Point2f> scene_corners(4);
    Mat H;


    detector.detect( image, kp_image );
    extractor.compute( image, kp_image, des_image );

    matcher.knnMatch(des_object, des_image, matches, 2);

    for(int i = 0; i < min(des_image.rows-1,(int) matches.size()); i++) //THIS LOOP IS SENSITIVE TO SEGFAULTS
    {
        if((matches[i][0].distance < 0.6*(matches[i][1].distance)) && ((int) matches[i].size()<=2 && (int) matches[i].size()>0))
        {
            good_matches.push_back(matches[i][0]);
        }
    }



    //Draw only "good" matches


    drawMatches( char1, kp_object, image, kp_image, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );

    if (good_matches.size() >= 4)
    {
        for( int i = 0; i < good_matches.size(); i++ )
        {
            //Get the keypoints from the good matches
            obj.push_back( kp_object[ good_matches[i].queryIdx ].pt );
            scene.push_back( kp_image[ good_matches[i].trainIdx ].pt );
            cout<<angleBetween(obj[i],scene[i])<<endl; //angles between images

        }

        H = findHomography( obj, scene, CV_RANSAC );


        perspectiveTransform( obj_corners, scene_corners, H);

       // cout<<angleBetween(obj[0], scene[0])<<endl;


        //Draw lines between the corners (the mapped object in the scene image )

    }

    //Show detected matches
    // resize(img_matches, img_matches, Size(img_matches.cols/2, img_matches.rows/2));

    imshow( "Good Matches", img_matches );
    waitKey();

    return 0;
}

How to rotate the Incoming Image automatically so that it will align perfectly with the Template Image. 如何自动旋转传入图像,使其与模板图像完美对齐。 i have the following code which rotate the Incoming Image manually 90 degree anticlockwise 我有以下代码,可以手动将传入图片逆时针旋转90度

import numpy as np
import cv2

img = cv2.imread('letter defect f90.png',0)
rows,cols = img.shape

M = cv2.getRotationMatrix2D((cols/2,rows/2),90,1)
dst = cv2.warpAffine(img,M,(cols,rows))

img2 = cv2.imwrite('result_rotate.png',dst)

img3 = cv2.imread('letter f.png')
img4 = cv2.imread('result_rotate.png')

difference = cv2.subtract(img3, img4)

result = np.any(difference) 

if result is True:
    print ("The images are the same")
else:
    cv2.imshow("result.jpg", difference)
    print ("the images are different")

I was thinking of coming up with a solution after I got your comment. 得到您的评论后,我正在考虑提出解决方案。 My answer may not be perfect but hope it gives some idea to a better solution. 我的回答可能并不完美,但希望它能为更好的解决方案提供一些参考。

Perform a contour operation of the image you intend to find rotation for. 对要旋转的图像执行轮廓操作。 Fit an ellipse around the contour you have obtained. 在获得的轮廓周围拟合一个椭圆。 Now based on the obtained ellipse you can come to a conclusion whether the image is vertical, horizontal or inclined in any other direction. 现在,基于获得的椭圆,您可以得出结论,图像是垂直的,水平的还是在任何其他方向上都是倾斜的。

-If your contour object is broad, the major axis of the ellipse fit will be horizontal. -如果轮廓对象较宽,则椭圆拟合的主轴将为水平。

-If your contour object is thin and tall, the major axis of the ellipse fit will be vertical. -如果轮廓对象又细又高,则椭圆拟合的主轴将是垂直的。

Now if the obtained ellipse fit is neither vertical nor horizontal, you will need to perform an orientation alignment. 现在,如果获得的椭圆拟合既不是垂直的也不是水平的,则需要执行方向对齐。

Hope it helps!!!! 希望能帮助到你!!!!

EDIT 编辑

I guess you want to rotate your image. 我想您想旋转图像。 You can use the getRotationMatrix2D() function available in the OpenCV library (snippet from here ): 您可以使用OpenCV库中可用的getRotationMatrix2D()函数( 此处的摘录):

(x, y) = img.shape[:2]
center = (y / 2, x / 2)

Mat = cv2.getRotationMatrix2D(center, 90, 1.0)
rotate = cv2.warpAffine(img, Mat, (y, x))
cv2.imwrite("rotated.jpg", rotate)
  • 1st parameter : Initially you obtain the center of the image. 第一个参数:最初获取图像的中心
  • 2nd parameter : Rotate the image around this center with an angle of your choice. 第二个参数:以您选择的角度围绕该中心旋转图像。
  • 3rd parameter : This is the scale . 第三个参数:这是刻度 It decides how big or small you want your image to be. 它决定了图像的大小。

Here is your original image: 这是您的原始图片:

在此处输入图片说明

This is the rotated image obtained: 这是获得的旋转图像:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM