基于SIFT / ORB的Homography estimation

SIFT

ORB

python 复制代码
import copy
import time

import cv2
import numpy as np


def draw_kpts(image0, image1, mkpts0, mkpts1, margin=10):
    H0, W0 = image0.shape
    H1, W1 = image1.shape
    H, W = max(H0, H1), W0 + W1 + margin
    out = 255 * np.ones((H, W), np.uint8)
    out[:H0, :W0] = image0
    out[:H1, W0+margin:] = image1
    out = np.stack([out]*3, -1)

    mkpts0, mkpts1 = np.round(mkpts0).astype(int), np.round(mkpts1).astype(int)
    # print(f"mkpts0.shape : {mkpts0.shape}")
    c = (0, 255, 0)
    for (new, old) in zip(mkpts0, mkpts1):
        x0, y0 = new.ravel()
        x1, y1 = old.ravel()
        # print(f"x0 : {x0}")
        # cv2.line(out, (x0, y0), (x1 + margin + W0, y1),
        #         color=c, thickness=1, lineType=cv2.LINE_AA)
        # display line end-points as circles
        cv2.circle(out, (x0, y0), 2, c, -1, lineType=cv2.LINE_AA)
        cv2.circle(out, (x1 + margin + W0, y1), 2, c, -1,
                lineType=cv2.LINE_AA)
        
    return out

if __name__ == "__main__":
    img0Path = "/training/datasets/orchard/orchard_imgs_/000130.jpg"
    img1Path = "/training/datasets/orchard/orchard_imgs_/000132.jpg"

    img0 = cv2.imread(img0Path, 0)
    img1 = cv2.imread(img1Path, 0)
    h, w = img0.shape

    mask = np.zeros_like(img0)
    mask[int(0.02 * h): int(0.98 * h), int(0.02 * w): int(0.98 * w)] = 255
    
    feature_detector_threshold = 20
    matcher_norm_type = cv2.NORM_HAMMING
    # detector = cv2.FastFeatureDetector_create(threshold=feature_detector_threshold)
    # extractor = cv2.ORB_create()
    # matcher = cv2.BFMatcher(matcher_norm_type)
    detector = cv2.SIFT_create(nOctaveLayers=3, contrastThreshold=0.02, edgeThreshold=20)
    extractor = cv2.SIFT_create(nOctaveLayers=3, contrastThreshold=0.02, edgeThreshold=20)
    matcher = cv2.BFMatcher(cv2.NORM_L2)

    # find static keypoints
    prev_keypoints = detector.detect(img0, mask)
    keypoints = detector.detect(img1, mask)

    # compute the descriptors
    prev_keypoints, prev_descriptors = extractor.compute(img0, prev_keypoints)
    keypoints, descriptors = extractor.compute(img1, keypoints)

    # Match descriptors.
    knnMatches = matcher.knnMatch(prev_descriptors, descriptors, k=2)

    # filtered matches based on smallest spatial distance
    matches = []
    spatial_distances = []
    max_spatial_distance = 0.25 * np.array([w, h])

    for m, n in knnMatches:
        if m.distance < 0.9 * n.distance:
            prevKeyPointLocation = prev_keypoints[m.queryIdx].pt
            currKeyPointLocation = keypoints[m.trainIdx].pt

            spatial_distance = (prevKeyPointLocation[0] - currKeyPointLocation[0],
                                prevKeyPointLocation[1] - currKeyPointLocation[1])

            if (np.abs(spatial_distance[0]) < max_spatial_distance[0]) and \
                    (np.abs(spatial_distance[1]) < max_spatial_distance[1]):
                spatial_distances.append(spatial_distance)
                matches.append(m)

    mean_spatial_distances = np.mean(spatial_distances, 0)
    std_spatial_distances = np.std(spatial_distances, 0)

    inliesrs = (spatial_distances - mean_spatial_distances) < 2.5 * std_spatial_distances

    goodMatches = []
    prevPoints = []
    currPoints = []
    for i in range(len(matches)):
        if inliesrs[i, 0] and inliesrs[i, 1]:
            goodMatches.append(matches[i])
            prevPoints.append(prev_keypoints[matches[i].queryIdx].pt)
            currPoints.append(keypoints[matches[i].trainIdx].pt)

    prevPoints = np.array(prevPoints)
    currPoints = np.array(currPoints)

     # find rigid matrix
    if (np.size(prevPoints, 0) > 4) and (np.size(prevPoints, 0) == np.size(prevPoints, 0)):
        H, inliesrs = cv2.estimateAffinePartial2D(prevPoints, currPoints, cv2.RANSAC)
    else:
        print('Warning: not enough matching points')
    
    print(f"H : {H}")

    out = draw_kpts(img0, img1, prevPoints, currPoints)
    cv2.imwrite("keypoints.jpg", out)
相关推荐
RoboWizard2 分钟前
固态硬盘对游戏帧数有影响吗?
人工智能
2301_768103493 小时前
AI视频创作Agent实战03:DeepSeek文案裂变与草稿版本控制
人工智能
火山引擎开发者社区3 小时前
Anker 首届黑客松挑战赛|9 月 7 日报名启动
人工智能
Dawson Zhu4 小时前
工作流与 Agent 的工程选型:从“控制权归属“看 LLM 应用架构
人工智能·语言模型·架构·aigc·agi
计算机源码社5 小时前
【大数据项目实战】基于大数据的影视内容生态综合质量分析与可视化-基于数据挖掘的影视内容类型共现与口碑聚类分析系统
大数据·人工智能·python·数据挖掘·数据分析·毕业设计·课程设计
C^h5 小时前
pytorch 适合初学者 0基础学习
人工智能·pytorch·python
Rocky Ding*5 小时前
【三年面试五年模拟】2026-09-06 拼多多 AI Agent研发岗秋招笔试4道算法题完整题解
论文阅读·人工智能·深度学习·机器学习·aigc·ai-native·拼多多
小柯南敲键盘5 小时前
跨马翻译:AI批量图片翻译工具,跨境电商视频字幕翻译与智能抠图一体搞定
人工智能·python·音视频
luckystar513~6 小时前
Geo + AI:【时空智能体】技术剖析
人工智能·ai·gis·geoai·空间智能体·时空智能体
吨吨ai6 小时前
2026年9月8日|GPT‑6 Astra + Codex:Pro 开发者的 AI Agent 工具链
人工智能·gpt