Harris特征点检测 | Datawhale 六月组队学习(task1)

我之前利用四个角点的位置特征找到了角点,详见:透视变换法校正轮廓(全过程) | python代码

1. 原理

1.1 公式

角点响应函数:
在这里插入图片描述在这里插入图片描述
因此:设定一个阈值,分数大于这个阈值的像素就对应角点。

1.2 参数设置

dst = cv2.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]])
blockSize—计算在时候的矩阵大小
Ksize—窗口大小
k—表示计算角度响应时候的参数大小,默认在0.04-0.06之间
阈值t—用来过滤角度响应

2. 初步实现

2.1 效果展示

原图:
在这里插入图片描述
效果图:
在这里插入图片描述

2.2 代码展示

import cv2
from matplotlib import pyplot as plt
import numpy as np

img = cv2.imread('D:/python_opencv/H_1.jpg')
cv2.namedWindow("img",cv2.cv2.WINDOW_FREERATIO)
cv2.imshow("img",img)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h,w = img.shape[0],img.shape[1]
#Harris角点检测
gray_img = np.float32(gray_img)
corners_img = cv2.cornerHarris(gray_img,blockSize=2, ksize=3, k=0.04)
cv2.imshow("corners_img",corners_img)
#膨胀
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
dst = cv2.dilate(corners_img, kernel)
cv2.imshow("dst",dst)

#阈值设定
img[dst > 0.005*dst.max()] = [225, 0, 0]
cv2.namedWindow("Harris",cv2.cv2.WINDOW_FREERATIO)
cv2.imshow('Harris', img)
count = 0
print(h,w)
#左上角
for i in range(h//2):
    for j in range(w//2):
        if  img[i][j][0] == 225:
            cv2.circle(img,(j,i),5,(0,255,255),0)
            count += 1
#右上角
for i in range(h//2):
    for j in range(w//2,w):
        if  img[i][j][0] == 225:
            cv2.circle(img,(j,i),5,(0,255,255),0)
            count += 1            
        
#左下角
for i in range(h//2,h):
    for j in range(w//2):
        if  img[i][j][0] == 225:
            cv2.circle(img,(j,i),5,(0,255,255),0)
            count += 1  
        
#右下角
for i in range(h//2,h):
    for j in range(w//2,w):
        if  img[i][j][0] == 225:
            cv2.circle(img,(j,i),5,(0,255,255),0)
            count += 1  


print(count)
cv2.namedWindow("final",cv2.cv2.WINDOW_FREERATIO)
cv2.imshow('final', img)
cv2.waitKey(0)        


3. 改进方案

要求:只保留4个角点

3.1 效果展示

原图:
在这里插入图片描述
效果图:
在这里插入图片描述

3.2 原理解释

每部分角点的存储方式是顺时针,见下图。所以左上和右上图在第一次循环时就得出来,左下图就需要循环到最后出来,右下图还需要精细化处理,暂不讨论。
在这里插入图片描述

3.3 代码展示

import cv2
from matplotlib import pyplot as plt
import numpy as np

img = cv2.imread('D:/python_opencv/H_1.jpg')
src = img.copy()
cv2.namedWindow("img",cv2.cv2.WINDOW_FREERATIO)
cv2.imshow("img",img)
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray_img, (7, 7), 0)
h,w = img.shape[0],img.shape[1]
#Harris角点检测
gray_img = np.float32(gray)
corners_img = cv2.cornerHarris(gray_img,blockSize=2, ksize=3, k=0.04)
cv2.imshow("corners_img",corners_img)
#膨胀
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
dst = cv2.dilate(corners_img, kernel)
cv2.imshow("dst",dst)

#阈值设定
img[dst > 0.005*dst.max()] = [225, 0, 0]
cv2.namedWindow("Harris",cv2.cv2.WINDOW_FREERATIO)
cv2.imshow('Harris', img)
count = 0
print(h,w)

upLeftX = 0
upLeftY = 0
downLeftX = 0
downLeftY = 0
upRightX = 0
upRightY = 0
downRightX = 0
downRightY = 0
#左上角
for i in range(h//2):
    for j in range(w//2):
        if  img[i][j][0] == 225:
            cv2.circle(img,(j,i),5,(0,255,255),-1)
            count += 1
            if upLeftX == 0 and upLeftY == 0 :
                upLeftX = i
                upLeftY = j
                break
            if upLeftX or upLeftY:
                break
  

#右上角
for i in range(h//2):
    for j in range(w//2,w):
        if  img[i][j][0] == 225:
            cv2.circle(img,(j,i),5,(0,255,255),-1)
            count += 1 
            if upRightX == 0 and upRightY == 0:
                upRightX = i
                upRightY = j
                break
            if upRightX or upRightY:
                break
           

#左下角
for i in range(h//2,h):
    for j in range(w//2):
        if  img[i][j][0] == 225:
            cv2.circle(img,(j,i),5,(0,255,255),-1)
            count += 1  
            downLeftX = i
            downLeftY = j

   
#右下角
for i in range(h//2,h):
    for j in range(w//2,w):
        if  img[i][j][0] == 225:
            cv2.circle(img,(j,i),5,(0,255,255),-1)
            count += 1  
            downRightX = i
            downRightY = j
cv2.line(img, (0,h//2), (w,h//2), (0,0,255))
cv2.line(img, (w//2,0), (w//2,h), (0,0,255))           
cv2.namedWindow("all_Harris",cv2.cv2.WINDOW_FREERATIO)
cv2.imshow('all_Harris', img)

            
cv2.circle(src,(upLeftY,upLeftX),5,(0,255,255),-1)
cv2.circle(src,(upRightY,upRightX),5,(0,255,255),-1)
cv2.circle(src,(downLeftY,downLeftX),5,(0,255,255),-1)
cv2.circle(src,(downRightY,downRightX),5,(0,255,255),-1)


print(count)
cv2.namedWindow("final",cv2.cv2.WINDOW_FREERATIO)
cv2.imshow('final', src)
cv2.waitKey(0)        


猜你喜欢

转载自blog.csdn.net/weixin_42326479/article/details/106933629