Python: 在opencv/python中运行estimateRigidTransform时出现8uC1或8uC3错误

3 投票
1 回答
1242 浏览
提问于 2025-04-18 10:37

我现在有两个匹配的点集,这些点集被存储在一个浮点数的numpy数组里:

points1 = 
[[  346.70220947  9076.38476562]
 [  922.99554443  9096.4921875 ]
 [  776.96466064  9108.79101562]
 [  449.0173645   9080.61816406]
 [ 2843.19433594  1226.93212891]
 [  779.95275879  9094.76855469]
 [  451.46853638  9092.5078125 ]
 [ 3981.4621582   1237.50964355]
 [  132.38700867  9086.7890625 ]
 [  819.10943604  8286.74023438]
 [ 1963.64025879  1220.06921387]
 [ 1253.79321289  9095.75292969]]

points2 = 
[[ 55110.36328125   9405.07519531]
 [ 55686.71875      9423.63574219]
 [ 55540.8515625    9435.80078125]
 [ 55212.58203125   9408.00585938]
 [ 57598.76171875   1551.92956543]
 [ 55543.78125      9421.88769531]
 [ 55214.40625      9420.46972656]
 [ 58737.41796875   1561.14831543]
 [ 54895.9296875    9414.58203125]
 [ 55581.87109375   8613.87011719]
 [ 56718.76953125   1546.02197266]
 [ 56017.8125       9422.52050781]]

我想运行以下代码:

affine = cv2.estimateRigidTransform(points2,points1,True)
print affine

这样我就可以生成一个仿射矩阵,然后把它转换成一个世界文件(.tfw)。这个世界文件是给GIS软件用的,能够实时显示这些数据。

目前我遇到了一个错误:

Both input images must have either 8uC1 or 8uC3 type in function cvEstimateRigidTransform

我不太明白这是怎么回事。我以为只要有6对或更多的点,我就可以把这两个点集作为参数使用。

如果你有任何想法或建议,我会非常感激!

1 个回答

0

我也遇到了一个奇怪的错误,不过是在Java中。在我的情况下,似乎estimateRigidTransform这个函数没办法识别我给它的两个Mat图像其实是两个二维点集。所以我想了个办法,把我的匹配点从MatOfKeyPoint类型转换成MatOfPoint2f类型。

下面是完整的Java代码(虽然不是Python,但也许对你有帮助):

更新:过滤你的匹配点很重要,因为如果不这样做,你可能会得到一个空数组作为变换的结果。

    FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB);
    DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
    DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);

    // Load First Image
    Mat img1 = Imgcodecs.imread("img1_path", Imgcodecs.IMREAD_GRAYSCALE);
    Mat img1_descriptors = new Mat();
    MatOfKeyPoint img1_keypoints_mat = new MatOfKeyPoint();

    // Detect KeyPoints
    detector.detect(img1, img1_keypoints_mat);
    descriptor.compute(img1, img1_keypoints_mat, img1_descriptors);

    // Load Second Image
    Mat img2 = Imgcodecs.imread("img2_path", Imgcodecs.IMREAD_GRAYSCALE);
    Mat img2_descriptors = new Mat();
    MatOfKeyPoint img2_keypoints_mat = new MatOfKeyPoint();

    // Detect KeyPoints
    detector.detect(img2, img2_keypoints_mat);
    descriptor.compute(img2, img2_keypoints_mat, img2_descriptors);

    // Match KeyPoints
    MatOfDMatch matOfDMatch = new MatOfDMatch();
    matcher.match(img1_descriptors, img2_descriptors, matOfDMatch);

    // Filtering the matches
    List<DMatch> dMatchList = matOfDMatch.toList();
    Double max_dist = 0.0;
    Double min_dist = 100.0;

    for(int i = 0; i < img1_descriptors.rows(); i++){
        Double dist = (double) dMatchList.get(i).distance;
        if(dist < min_dist) min_dist = dist;
        if(dist > max_dist) max_dist = dist;
    }
    LinkedList<DMatch> good_matches = new LinkedList<>();
    for(int i = 0; i < img1_descriptors.rows(); i++){
        if(dMatchList.get(i).distance < 3*min_dist){
            good_matches.addLast(dMatchList.get(i));
        }
    }

    // Converting to MatOfPoint2f format
    LinkedList<Point> img1_points_list = new LinkedList<>();
    LinkedList<Point> img2_points_list = new LinkedList<>();

    List<KeyPoint> img1_keyPoints_list = img1_keypoints_mat.toList();
    List<KeyPoint> img2_keyPoints_list = img2_keypoints_mat.toList();

    int limit = good_matches.size();
    for(int i = 0; i < limit; i++){
        img1_points_list.addLast(img1_keyPoints_list.get(good_matches.get(i).queryIdx).pt);
        img2_points_list.addLast(img2_keyPoints_list.get(good_matches.get(i).trainIdx).pt);
    }

    MatOfPoint2f img1_point2f_mat = new MatOfPoint2f();
    img1_point2f_mat.fromList(img1_points_list);

    MatOfPoint2f img2_point2f_mat = new MatOfPoint2f();
    img2_point2f_mat.fromList(img2_points_list);

    // Draw match points
    Mat output = new Mat();
    Features2d.drawMatches(img1, img1_keypoints_mat, img2, img2_keypoints_mat, matOfDMatch, output);
    Imgcodecs.imwrite("output.png", output);

    Mat result = Video.estimateRigidTransform(img1_point2f_mat, img2_point2f_mat, true);
    printMat(result); // Printing the optimal affine transformation 2x3 array

    // The following variables correspond to the estimateRigidTransform result as shown here: https://stackoverflow.com/a/29511091/5165833
    double a = result.get(0,0)[0];
    double b = result.get(0,1)[0];
    double d = result.get(1,1)[0];
    double c = result.get(1,0)[0];

    // Solving for scale as shown in the link above
    double scale_x = Math.signum(a) * Math.sqrt( (a*a) + (b*b) );
    double scale_y = Math.signum(d) * Math.sqrt( (c*c) + (d*d) );

    System.out.println("a = "+a);
    System.out.println("b = "+b);
    System.out.println("scale_x = "+scale_x);
    System.out.println("scale_y = "+scale_y);
}

public static void printMat(Mat m)
{
    for (int x=0; x < m.height(); x++)
    {
        for (int y=0; y < m.width(); y++)
        {
            System.out.printf("%f",m.get(x,y)[0]);
            System.out.printf("%s"," ");
        }
        System.out.printf("\n");
    }
}

撰写回答