gpt4 book ai didi

image - 估计两个图像之间的仿射变换

转载 作者:太空宇宙 更新时间:2023-11-03 21:00:35 26 4
gpt4 key购买 nike

我有一个示例图片:

enter image description here

我使用以下扭曲矩阵应用仿射变换:

[[ 1.25  0.    -128  ]
[ 0. 2. -192 ]]

并从结果中裁剪出 128x128 的部分以获得输出图像:

enter image description here

现在,我想通过比较样本和输出图像来估计扭曲矩阵和裁剪大小/位置。我使用 SURF 检测特征点,并通过暴力匹配它们:

enter image description here

有很多匹配项,我保留了其中最好的三个(按距离),因为这是估计仿射变换所需的数目。然后,我使用这 3 个关键点来估计使用 getAffineTransform 的仿射变换。然而,它返回的转换是完全错误的:

-0.00 1.87 -6959230028596648489132997794229911552.00 
0.00 -1.76 -0.00

我做错了什么?源代码如下。

执行仿射变换(Python):

"""Apply an affine transform to an image."""
import cv
import sys
import numpy as np
if len(sys.argv) != 10:
print "usage: %s in.png out.png x1 y1 width height sx sy flip" % __file__
sys.exit(-1)
source = cv.LoadImage(sys.argv[1])
x1, y1, width, height, sx, sy, flip = map(float, sys.argv[3:])
X, Y = cv.GetSize(source)
Xn, Yn = int(sx*(X-1)), int(sy*(Y-1))
if flip:
arr = np.array([[-sx, 0, sx*(X-1)-x1], [0, sy, -y1]])
else:
arr = np.array([[sx, 0, -x1], [0, sy, -y1]])
print arr
warp = cv.fromarray(arr)
cv.ShowImage("source", source)
dest = cv.CreateImage((Xn, Yn), source.depth, source.nChannels)
cv.WarpAffine(source, dest, warp)
cv.SetImageROI(dest, (0, 0, int(width), int(height)))
cv.ShowImage("dest", dest)
cv.SaveImage(sys.argv[2], dest)
cv.WaitKey(0)

从两个图像估计仿射变换(C++):

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

#include <algorithm>

using namespace cv;

void readme();

bool cmpfun(DMatch a, DMatch b) { return a.distance < b.distance; }

/** @function main */
int main( int argc, char** argv )
{
if( argc != 3 )
{
return -1;
}

Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE );

if( !img_1.data || !img_2.data )
{
return -1;
}

//-- Step 1: Detect the keypoints using SURF Detector
int minHessian = 400;

SurfFeatureDetector detector( minHessian );

std::vector<KeyPoint> keypoints_1, keypoints_2;

detector.detect( img_1, keypoints_1 );
detector.detect( img_2, keypoints_2 );

//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;

Mat descriptors_1, descriptors_2;

extractor.compute( img_1, keypoints_1, descriptors_1 );
extractor.compute( img_2, keypoints_2, descriptors_2 );

//-- Step 3: Matching descriptor vectors with a brute force matcher
BFMatcher matcher(NORM_L2, false);
std::vector< DMatch > matches;
matcher.match( descriptors_1, descriptors_2, matches );

double max_dist = 0;
double min_dist = 100;

//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors_1.rows; i++ )
{ double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}
printf("-- Max dist : %f \n", max_dist );
printf("-- Min dist : %f \n", min_dist );

//-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist )
//-- PS.- radiusMatch can also be used here.
sort(matches.begin(), matches.end(), cmpfun);
std::vector< DMatch > good_matches;
vector<Point2f> match1, match2;
for (int i = 0; i < 3; ++i)
{
good_matches.push_back( matches[i]);
Point2f pt1 = keypoints_1[matches[i].queryIdx].pt;
Point2f pt2 = keypoints_2[matches[i].trainIdx].pt;
match1.push_back(pt1);
match2.push_back(pt2);
printf("%3d pt1: (%.2f, %.2f) pt2: (%.2f, %.2f)\n", i, pt1.x, pt1.y, pt2.x, pt2.y);
}

//-- Draw matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2, good_matches, img_matches,
Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);

//-- Show detected matches
imshow("Matches", img_matches );
imwrite("matches.png", img_matches);

waitKey(0);

Mat fun = getAffineTransform(match1, match2);
for (int i = 0; i < fun.rows; ++i)
{
for (int j = 0; j < fun.cols; j++)
{
printf("%.2f ", fun.at<float>(i,j));
}
printf("\n");
}

return 0;
}

/** @function readme */
void readme()
{
std::cout << " Usage: ./SURF_descriptor <img1> <img2>" << std::endl;
}

最佳答案

cv::Mat getAffineTransform 返回的是 double ,而不是 float 。您得到的矩阵可能没问题,您只需将循环中的 printf 命令更改为

printf("%.2f ", fun.at<double>(i,j));

或更简单:将此手动输出替换为

std::cout << fun << std::endl;

它更短,您不必自己关心数据类型。

关于image - 估计两个图像之间的仿射变换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13758570/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com