Opencv,通过仿射变换转换图像

时间:2014-08-02 13:13:21

标签: opencv transform ellipse affinetransform

left image right image

我想将第一张图片转换为第二张图片,我想也许是仿射转换。我的问题和疑问如下:

(1)。正如我上面提到的,我认为变换是仿射变换。因此,第一步是通过沿顺时针方向单击第一个图像中的三个角点(从鼠标回调函数返回坐标)找到三对对应点,并将其对应点设置为特定坐标(每个角点之间的距离已知) 。第二步是使用getAffineTransform()和warpAffine()方法来实现仿射变换。但是这种方法已经证明不够好(见第三张图),所以有什么想法可以改善结果吗? third image

我的代码如下所示:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2/features2d/features2d.hpp"

#include <stdio.h>
#include <vector>
#include <iostream>
#include <fstream>

using namespace std;
using namespace cv;


Mat org;
int n=0;
vector<Point> capturePoint;

void on_mouse(int event,int x,int y,int flags,void *ustc)
{
    Point pt;
    char coordinateName[16];

    if (event == CV_EVENT_LBUTTONDOWN)
    {
        pt = Point(x,y);
        cout<<x<<" "<<y<<endl;
        capturePoint.push_back(pt);
        n++;

        circle(org,pt,2,Scalar(255,0,0,0),CV_FILLED,CV_AA,0);
        sprintf(coordinateName,"(%d,%d)",x,y);
        putText(org,coordinateName,pt,FONT_HERSHEY_SIMPLEX,0.5,Scalar(0,0,0,255),1,8);

        //imshow("org",org);

        if(n>=4)
        {
            imshow("org",org);
            cvDestroyAllWindows();
        }
    }
}

int main()
{
    org = imread("1-3.jpg",1);

    namedWindow("org",1);
    setMouseCallback("org",on_mouse,0);// mouse callback;

    imshow("org",org);
    waitKey(0);
    //cout<<capturePoint.size()<<endl;

    //three pairs of corresponding points;

    Point2f srcPoint[3];
    Point2f dstPoint[3];
    srcPoint[0]=capturePoint[0];//mouse click along clockwise direction;
    srcPoint[1]=capturePoint[1];
    srcPoint[2]=capturePoint[2];
    //srcPoint[3]=capturePoint[3];

    dstPoint[0]=Point(0,0);//distances between each corner point are known;
    dstPoint[1]=Point(640,0);//width=320,height=220;
    dstPoint[2]=Point(640,440);
    //dstPoint[3]=Point(0,220);

    Mat warpDst=Mat(org.rows, org.cols, org.type());
    //Mat warpMat = findHomography( srcPoint, dstPoint, 0 );
    Mat warpMat = getAffineTransform(srcPoint,dstPoint);
    warpAffine(org,warpDst,warpMat,org.size());//affine transformation;
    imshow("Warp",warpDst);

    waitKey(0);

    return 0;
}

(2)。我想在没有人工干预的情况下实现转换,即不需要手动选择点,因此我想在第一个图像中使用椭圆中心及其对应点来实现仿射变换。我的问题是,如果椭圆中心可用于实现仿射变换,如果可以,则如何检测椭圆中心。

(3)。我使用canny方法获得最大轮廓,并应用cornerHarris来检测最大轮廓的角点。我发现每个角落可能有一些彼此靠近的候选点。那么如何获得四个&#34;&#34;角点?

1 个答案:

答案 0 :(得分:0)

我使用cv2(python绑定)玩你的图像。它仍然不完美,但您可以使用参数进一步改进。较小的k改善了角点检测。门槛也很重要。

enter image description here

import cv2
from pylab import *

fp = "qkwWV.jpg"

img = cv2.imread(fp)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# edge and corner detection using cornerHarris
blockSize = 16
ksize  = 7
k = 0.005
corners = cv2.cornerHarris(gray, blockSize, ksize, k)
cv2.normalize( corners, corners, 0, 255, cv2.NORM_MINMAX, cv2.CV_32F, None)

# play with threshold until only 4 corners are left.
figure()
thrs = 173
imshow(corners>thrs, cmap=cm.gray)

# get the center coordinates of 4 groups using k-means
y,x = np.where(corners>thrs)
candidates = np.array(zip(x,y)).astype(np.float32)

term_crit = (cv2.TERM_CRITERIA_EPS, 30, 0.1)
flags = cv2.KMEANS_RANDOM_CENTERS
ret, labels, centers = cv2.kmeans(candidates, 4, term_crit, 10, flags)

# draw cross haris on the original image
centers = centers.astype(np.int)
L = 40
for _x, _y in centers: 
    cv2.line(img, (_x-L, _y), (_x+L, _y), (255,0,0), 3)
    cv2.line(img, (_x, _y-L), (_x, _y+L), (255,0,0), 3)

figure()
imshow(img)
show()