【问题标题】:Opencv , transforming image by affine transformationOpencv,通过仿射变换变换图像
【发布时间】:2014-09-25 13:16:03
【问题描述】:

我想将第一张图像转换为第二张图像,我想可能是仿射变换。我的问题和疑问如下:

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

我的代码如下所示:

#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)。我使用精明的方法来获得最大的轮廓,并应用cornerHarris 来检测最大轮廓的角点。我发现每个角落都可能有一些彼此靠近的候选点。那么如何获得四个“真”角点呢?

【问题讨论】:

  • 我认为仿射变换就足够了。使用cornerharris检测纸的角落怎么样? docs.opencv.org/modules/imgproc/doc/… 这将使过程自动化,并为您提供更准确的仿射变换坐标。
  • @otterb 很抱歉这么晚才回复你。我已经厌倦了cornerHarris() 方法,你可能知道,它会检测到其他不需要的角点。我想要的是四个“真正”的角点。
  • 您尝试过圆形/椭圆检测方法吗?否则,如果 Harris 总是检测到所有 TRUE 角点(以及其他一些),您也许可以通过一些启发式方法选择那些真正的角点。
  • 第三张图片到底有什么问题?这似乎是相当准确的。
  • @Dennis 你好,看看左上角的椭圆,应该是一个“绝对圆”。另一方面,左下角丢失了。

标签: opencv transform ellipse affinetransform


【解决方案1】:

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

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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-04
    相关资源
    最近更新 更多