在OpenCV里Shi-Tomasi角检测

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/caimouse/article/details/102647576

目标:学习Shi-Tomasi角检测, cv.goodFeaturesToTrack()函数。

 

理论:

在前面的文章学习过Harris角检测,到1994年时J. Shi和C. Tomasi对这个角检测算法进行了改进,发表了论文《Good Features to Track》,

在论文里说明使用两个特征值中较小的一个大于最小阈值,公式如下:

用这个公式替代Harris角公式:

相当于下图的区域寻找:

在这里找到最小的lambda1和lambda2值,并且让它大于lambda最小值,就是绿色区或。可以用下面算法来计算:

1)计窗口里X轴和Y轴的导数。

2)计算lambda1和lambda2,并取最小值保存起来。

3)根据角的质量水平判断。

4)对角按lambda排序

5)对排序结果计算两个角点之间的最短欧式距离。

用下面例子来演示:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt
from scipy import signal as sig

def gradient_x(imggray):
    ##Sobel算子求导
    kernel_x = np.array([[-1, 0, 1],[-2, 0, 2],[-1, 0, 1]],np.float)
    return sig.convolve2d(imggray, kernel_x, mode='same')
def gradient_y(imggray):
    kernel_y = np.array([[1, 2, 1], [0, 0, 0], [-1, -2, -1]],np.float)
    return sig.convolve2d(imggray, kernel_y, mode='same')
def distance(p1, p2): #欧式距离
  y, x = p1
  v, u = p2
  return ((y - v) ** 2 + (x - u) ** 2) ** 0.5
#读取文件
img = cv2.imread('corner1.png',0)

newImg = img.copy() #拷贝文件
color_img = cv2.cvtColor(newImg, cv2.COLOR_GRAY2RGB) #转换为彩色图片,以便标记红色

window_size = 6 #窗口大小
k = 0.04 #K常数
qualityLevel = 0.01 #角点的质量水平
maxCorners = 25 #想要检测到的角点数目。
minDistance = 10 #两个角点之间的最短欧式距离。

I_x = gradient_x(img)#
I_y = gradient_y(img)#

Ixx = I_x**2
Ixy = I_y*I_x
Iyy = I_y**2

offset = window_size//2
height = img.shape[0]
width = img.shape[1]
#
scored_image_gradient = np.zeros((height,width), np.float32)

for y in range(offset, height-offset):
    for x in range(offset, width-offset):
        Sxx = np.sum(Ixx[y-offset:y+1+offset, x-offset:x+1+offset])
        Syy = np.sum(Iyy[y-offset:y+1+offset, x-offset:x+1+offset])
        Sxy = np.sum(Ixy[y-offset:y+1+offset, x-offset:x+1+offset])

        #查找角点,min(lambda1, lambda2)
        scored_image_gradient[y,x] = min(Sxx, Syy)
#角点的质量水平
good_corners = []
for y in range(height):
    for x in range(width):
        if scored_image_gradient.item(y,x) >= qualityLevel:
            good_corners.append((y,x))
#排序
good_corners.sort(key=lambda k:-scored_image_gradient[k])
top_corners = [good_corners.pop(0)]
for c in good_corners:
    distance_curr = lambda corner: distance(c, corner)
    if max(map(distance_curr, top_corners)) >= minDistance:
      top_corners.append(c)
      y, x = c
      color_img.itemset((y, x, 0), 0)
      color_img.itemset((y, x, 1), 0)
      color_img.itemset((y, x, 2), 255)
    if len(top_corners) == maxCorners:
      break

#显示图片
cv2.imshow('img',img)
cv2.imshow('color_img',color_img)
           
cv2.waitKey(0)
cv2.destroyAllWindows()

结果输出如下:

在OpenCV里使用下面的函数:

其中参数:

image:输入图像,一般是灰度图像。

maxCorners: 想要检测到的角点数目。

qualtyLevel: 角点的质量水平,0-1之间。它代表了角点的最低质量,实际用于过滤角点的最小特征值是qualtyLevel与图像中最大特征值的乘积,所以qualtyLevel的值不应超过1(常用的值为0.1或0.01)。低于这个值的所有角点都会被忽略。

minDistance: 两个角点之间的最短欧式距离。

mask: 是一幅像素值为布尔类型的像素,用于指定输入图像中蚕吐角点计算的像素点。

blockSize:计算导数的自相关矩阵时指定点的领域,默认为3,采用小窗口计算的结果比单点(也就是blockSize为1)计算的效果要好。

useHarrisDetector: 默认值为0,若非0,则函数使用Harris的角点定义

K: 当useHarrisDetector非0,则K为用于设置hessian自相关矩阵即对hessian行列式的相对权值的权值系数。

corners:返回(x,y)的序列

演示例子如下:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.csdn.net/caimouse/article/details/51749579
#
import numpy as np
import cv2
from matplotlib import pyplot as plt

#读取文件
img = cv2.imread('corner1.png',0)

newImg = img.copy() #拷贝文件
color_img = cv2.cvtColor(newImg, cv2.COLOR_GRAY2RGB) #转换为彩色图片,以便标记红色

corners = cv2.goodFeaturesToTrack(img,25,0.01,10) #找到25个角
corners = np.int0(corners) #转换为索引数组类型返回,np.int0等于np.intp

for i in corners:  #遍历角进行标记
    x,y = i.ravel()
    cv2.circle(color_img,(x,y),3,255,-1)


#显示图片
cv2.imshow('img',img)
cv2.imshow('color_img',color_img)
           
cv2.waitKey(0)
cv2.destroyAllWindows()

结果输出如下:

https://blog.csdn.net/caimouse/article/details/51749579

 

猜你喜欢

转载自blog.csdn.net/caimouse/article/details/102647576
今日推荐