python 3.7.11

opencv3.4.2.16

import numpy as np                             # numpy
import cv2 as cv                               # opencv 库
import itertools as it                         # 迭代器
from multiprocessing.pool import ThreadPool    # 多进程
from matplotlib import pyplot as plt           # 画图工具
import os


FLANN_INDEX_KDTREE = 0
FLANN_INDEX_LSH = 6

def affine_skew(tilt, phi, img, mask=None):
    h, w = img.shape[:2]
    if mask is None:
        mask = np.zeros((h, w), np.uint8)
        mask[:] = 255
    A = np.float32([[1, 0, 0], [0, 1, 0]])
    if phi != 0.0:
        phi = np.deg2rad(phi)
        s, c = np.sin(phi), np.cos(phi)
        A = np.float32([[c, -s], [s, c]])
        corners = [[0, 0], [w, 0], [w, h], [0, h]]
        tcorners = np.int32(np.dot(corners, A.T))
        x, y, w, h = cv.boundingRect(tcorners.reshape(1, -1, 2))
        A = np.hstack([A, [[-x], [-y]]])
        img = cv.warpAffine(img, A, (w, h), flags=cv.INTER_LINEAR, borderMode=cv.BORDER_REPLICATE)
    if tilt != 1.0:
        s = 0.8 * np.sqrt(tilt * tilt - 1)
        img = cv.GaussianBlur(img, (0, 0), sigmaX=s, sigmaY=0.01)
        img = cv.resize(img, (0, 0), fx=1.0 / tilt, fy=1.0, interpolation=cv.INTER_NEAREST)
        A[0] /= tilt
    if phi != 0.0 or tilt != 1.0:
        h, w = img.shape[:2]
        mask = cv.warpAffine(mask, A, (w, h), 
             flags=cv.INTER_NEAREST)
    ai = cv.invertAffineTransform(A)
    return img, mask, ai


def affine_detect(detector, img, mask=None, pool=None):
    params = [(1.0, 0.0)]
    for t in 2 ** (0.5 * np.arange(1, 6)):
        for phi in np.arange(0, 180, 72.0 / t):
            params.append((t, phi))

    def f(p):
        t, phi = p
        timg, tmask, Ai = affine_skew(t, phi, img)
        keypoints, descrs = detector.detectAndCompute(timg, tmask)
        for kp in keypoints:
            x, y = kp.pt
            kp.pt = tuple(np.dot(Ai, (x, y, 1)))
        if descrs is None:
            descrs = []
        return keypoints, descrs

    keypoints, descrs = [], []
    if pool is None:
        ires = it.imap(f, params)
    else:
        ires = pool.imap(f, params)



    for i, (k, d) in enumerate(ires):
        # print('affine sampling: %d / %d\r' % (i + 1, len(params)), end='')
        keypoints.extend(k)
        descrs.extend(d)

    return keypoints, np.array(descrs)


#初始化算法
def init_feature(name):
    chunks = name.split('-')
    if chunks[0] == 'sift':
        detector = cv.xfeatures2d.SIFT_create()
        norm = cv.NORM_L2
    elif chunks[0] == 'surf':
        detector = cv.xfeatures2d.SURF_create(800)
        norm = cv.NORM_L2
    elif chunks[0] == 'orb':
        detector = cv.ORB_create(800)
        norm = cv.NORM_HAMMING
    elif chunks[0] == 'akaze':
        detector = cv.AKAZE_create()
        norm = cv.NORM_HAMMING
    elif chunks[0] == 'brisk':
        detector = cv.BRISK_create()
        norm = cv.NORM_HAMMING
    else:
        return None, None
    if 'flann' in chunks:
        if norm == cv.NORM_L2:
            flann_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
        else:
            flann_params = dict(algorithm=FLANN_INDEX_LSH,
                                table_number=6,  # 12
                                key_size=12,  # 20
                                multi_probe_level=1)  # 2
   

def main(img1, img2):
    feature_name = 'orb-flann'
    detector, matcher = init_feature(feature_name)

    pool = ThreadPool(processes=cv.getNumberOfCPUs())

    kp1, desc1 = affine_detect(detector, img1, pool=pool)
    kp2, desc2 = affine_detect(detector, img2, pool=pool)

    matches = matcher.knnMatch(desc1, desc2, k=2)

    # lowe‘s过滤
    good = []
    for m, n in matches:
        if m.distance < 0.7 * n.distance:
            good.append(m)
    ratio1 = len(good) / len(matches)
    print('匹配率1', ratio1)
    # ransac 随机抽样一直过滤
    min_match_count = 10  # ransac阈值,期望匹配的好点最低数目 (根据项目判断)
    inLiner = 0  # 符合ransac算法变换矩阵的好点

    if len(good) > min_match_count:

        src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
        dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)

        # M: 3x3 变换矩阵.
        M, mask = cv.findHomography(src_pts, dst_pts, cv.RANSAC, 10.0)
        matchesMask = mask.ravel().tolist()
         for i in range(len(matchesMask)):
            if matchesMask[i] == 1:
                inLiner += 1

        ratio2 = inLiner / len(matchesMask)
        # return ratio1, ratio2, len(matches), len(good), inLiner
        print('匹配率2',ratio2)
        draw_params = dict(matchColor=(0, 255, 0),
                           singlePointColor=(0, 0, 255),
                           matchesMask=matchesMask,
                           flags=0)

        img3 = cv.drawMatches(img1, kp1, img2, kp2, good, None, **draw_params)
        plt.imshow(img3), plt.show()
    else:
        # 没有足够多的好点可以认为直接不匹配
        print('Done')
    # return ratio1, 0, len(matches), len(good), inLiner


if __name__ == '__main__':
     img1 = cv.imread('original/12.jpg', 0)
     img2 = cv.imread('target/12.jpg', 0) 
     main(img2, img1)

 

posted on 2023-10-23 16:36  皮五辣子  阅读(31)  评论(0编辑  收藏  举报