实验记录——特征匹配实验

0 写在前面

现在好像知道应该做什么了,然后慢慢去努力就好了。mark一下,还有幸福课需要看。

1 图像增强与检测之间的联系——特征匹配

思路选自——《基于机器视觉的水下海参图像识别技术》山东大学 徐萌

原理

SIFT特征匹配算法是一种在不同空间尺度上的一种关键特征点匹配算法,通常键像素点的大小、方向和尺度信息来描述特征。SIFT特征具有旋转、尺度缩放不变性,信息量丰富,匹配过程快速且准确。

流程

原始图像->特征点检测+特征点描述->特征集

基本思路

将用于对照的图像组进行一定程度的旋转和偏置,然后进行SIFT特征匹配度分析。检查特征点是否增多。

2 实验记录

2.1 偏置

import cv2
import math
import numpy as np


path = r'G:\sift\c000113.jpg'
img = cv2.imread(path)
height, width = img.shape[:2]
if img.ndim == 3:
    channel = 3
else:
    channel = None

angle = 30
if int(angle / 90) % 2 == 0:
    reshape_angle = angle % 90
else:
    reshape_angle = 90 - (angle % 90)
reshape_radian = math.radians(reshape_angle)  # 角度转弧度
# 三角函数计算出来的结果会有小数,所以做了向上取整的操作。
new_height = math.ceil(height * np.cos(reshape_radian) + width * np.sin(reshape_radian))
new_width = math.ceil(width * np.cos(reshape_radian) + height * np.sin(reshape_radian))
if channel:
    new_img = np.zeros((new_height, new_width, channel), dtype=np.uint8)
else:
    new_img = np.zeros((new_height, new_width), dtype=np.uint8)

radian = math.radians(angle)
cos_radian = np.cos(radian)
sin_radian = np.sin(radian)
dx = 0.5 * new_width + 0.5 * height * sin_radian - 0.5 * width * cos_radian
dy = 0.5 * new_height - 0.5 * width * sin_radian - 0.5 * height * cos_radian
# ---------------前向映射--------------------
# for y0 in range(height):
#     for x0 in range(width):
#         x = x0 * cos_radian - y0 * sin_radian + dx
#         y = x0 * sin_radian + y0 * cos_radian + dy
#         new_img[int(y) - 1, int(x) - 1] = img[int(y0), int(x0)]  # 因为整体映射的结果会比偏移一个单位,所以这里x,y做减一操作。

# ---------------后向映射--------------------
dx_back = 0.5 * width - 0.5 * new_width * cos_radian - 0.5 * new_height * sin_radian
dy_back = 0.5 * height + 0.5 * new_width * sin_radian - 0.5 * new_height * cos_radian
# for y in range(new_height):
#     for x in range(new_width):
#         x0 = x * cos_radian + y * sin_radian + dx_back
#         y0 = y * cos_radian - x * sin_radian + dy_back
#         if 0 < int(x0) <= width and 0 < int(y0) <= height:  # 计算结果是这一范围内的x0,y0才是原始图像的坐标。
#             new_img[int(y), int(x)] = img[int(y0) - 1, int(x0) - 1]  # 因为计算的结果会有偏移,所以这里做减一操作。


# ---------------双线性插值--------------------
if channel:
    fill_height = np.zeros((height, 2, channel), dtype=np.uint8)
    fill_width = np.zeros((2, width + 2, channel), dtype=np.uint8)
else:
    fill_height = np.zeros((height, 2), dtype=np.uint8)
    fill_width = np.zeros((2, width + 2), dtype=np.uint8)
img_copy = img.copy()
# 因为双线性插值需要得到x+1,y+1位置的像素,映射的结果如果在最边缘的话会发生溢出,所以给图像的右边和下面再填充像素。
img_copy = np.concatenate((img_copy, fill_height), axis=1)
img_copy = np.concatenate((img_copy, fill_width), axis=0)
for y in range(new_height):
    for x in range(new_width):
        x0 = x * cos_radian + y * sin_radian + dx_back
        y0 = y * cos_radian - x * sin_radian + dy_back
        x_low, y_low = int(x0), int(y0)
        x_up, y_up = x_low + 1, y_low + 1
        u, v = math.modf(x0)[0], math.modf(y0)[0]  # 求x0和y0的小数部分
        x1, y1 = x_low, y_low
        x2, y2 = x_up, y_low
        x3, y3 = x_low, y_up
        x4, y4 = x_up, y_up
        if 0 < int(x0) <= width and 0 < int(y0) <= height:
            pixel = (1 - u) * (1 - v) * img_copy[y1, x1] + (1 - u) * v * img_copy[y2, x2] + u * (1 - v) * img_copy[y3, x3] + u * v * img_copy[y4, x4]  # 双线性插值法,求像素值。
            new_img[int(y), int(x)] = pixel


cv2.imshow('res', new_img)
cv2.waitKey()
cv2.destroyAllWindows()

cv2.imwrite(r'G:\sift\img_save.jpg',new_img)

2.2 特征点检验

import io
from PIL import Image, ImageTk
import tkinter as tk

import cv2
import numpy as np
MIN_MATCH_COUNT = 4

img1 = cv2.imread(r"G:\sift\c000113.jpg")
img2 = cv2.imread(r"G:\sift\img_save.jpg")
g1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
g2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
match = cv2.FlannBasedMatcher(dict(algorithm =2, trees =1), {})
kp1, de1 = sift.detectAndCompute(g1,None)
kp2, de2 = sift.detectAndCompute(g2,None)
m = match.knnMatch(de1, de2, 2)
m = sorted(m,key = lambda x:x[0].distance)
ok = [m1 for (m1, m2) in m if m1.distance < 0.7 * m2.distance]
med = cv2.drawMatches(img1, kp1, img2, kp2, ok, None)

cv2.imwrite(r"G:\sift\b.jpg", med)
#
# cv2.imshow("0", med)
# cv2.waitKey()
# cv2.destroyAllWindows()


def resize(w, h, w_box, h_box, pil_image):
     f1 = 1.0 * w_box / w  # 1.0 forces float division in Python2
     f2 = 1.0 * h_box / h
     factor = min([f1, f2])
     width = int(w * factor)
     height = int(h * factor)
     return pil_image.resize((width, height), Image.ANTIALIAS)

root = tk.Tk()
 # size of image display box you want
 # 期望图像显示的大小
w_box = 800
h_box = 1000

 # 以一个PIL图像对象打开
pil_image = Image.open(r'G:\sift\b.jpg')

 # get the size of the image
 # 获取图像的原始大小
w, h = pil_image.size

# resize the image so it retains its aspect ration
# but fits into the specified display box
# 缩放图像让它保持比例,同时限制在一个矩形框范围内
pil_image_resized = resize(w, h, w_box, h_box, pil_image)

# convert PIL image object to Tkinter PhotoImage object
# 把PIL图像对象转变为Tkinter的PhotoImage对象
tk_image = ImageTk.PhotoImage(pil_image_resized)

 # put the image on a widget the size of the specified display box
 # Label: 这个小工具,就是个显示框,小窗口,把图像大小显示到指定的显示框
label = tk.Label(root, image=tk_image, width=w_box, height=h_box)
# padx,pady是图像与窗口边缘的距离
label.pack(padx=5, pady=5)
root.mainloop()

实验结果

偏置结果
请添加图片描述
特征匹配结果
请添加图片描述

错误记录

错误描述:解决opencv错误AttributeError: module ‘cv2.cv2‘ has no attribute ‘xfeatures2d‘
错误原因:这个错误是由于opencv-contrib-python版本太新导致出现的问题,应该降低版本
解决方案:

pip install opencv-contrib-python==3.3.0.10
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值