当要求的点P位于一个区域的内部时,点p边缘是平缓的,它的梯度值为0,此时向量 的与p的梯度点积为0,;
当点p位于区域的边缘的时候,向量 与区域平行,而p的梯度值则与边缘垂直,此时向量 的与p的梯度点积为0。
这两种情况下,向量 与P点的梯度都是正交的。先假设起始角点q在实际亚像素级角点p附近,则我们可以在要求的p点的周围取到很多p点的梯度和相关向量 令其点积为0,然后就可以通过求解方程组,方程组的解就是角点q的亚像素精度的位置,也就是精确角点的位置。 (学习OpenCV里有讲到)
import cv2 as cv import numpy as np from matplotlib import pyplot as plt img = cv.imread('img/chessboard.png') img = cv.resize(img, (int(img.shape[1]*0.2), int(img.shape[0]*0.2))) gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY) gray = np.float32(gray) dst = cv.cornerHarris(gray, 2, 3, 0.04) dst = cv.dilate(dst, None) ret, dst = cv.threshold(dst, 0.01*dst.max(), 255, cv.THRESH_BINARY) dst = np.uint8(dst) cv.imwrite('img/thresh3.png', dst) ret, labels, stats, centroids = cv.connectedComponentsWithStats(dst) ''' connectedComponentsWithStats(image, labels=None, stats=None, centroids=None, connectivity=None, ltype=None) ret: 返回的标签的数量 labels: 输入图像的大小的矩阵,其中每个元素的值都等于其标签 Stats is a matrix of the stats that the function calculates. It has a length equal to the number of labels and a width equal to the number of stats. stats: 函数计算的统计信息的矩阵。它的行等于标签的数量,列数等于统计到的信息数量(5个)。 每个标签的统计输出,包括背景标签。 输出格式为[cv2.CC_STAT_LEFT, CV.CC_STAT_TOP, CV.CC_STAT_WIDTH, CV.CC_STAT_HEIGHT, CV.CC_STAT_AREA] CV.CC_STAT_LEFT: 最左边的(x)坐标,它是水平方向上边界框的包含开始 CV.CC_STAT_TOP: 最上边的(y)坐标,它是垂直方向上边界框的包含开始 CV.CC_STAT_TOP: 边界框的水平大小 CV.CC_STAT_TOP: 边界框的垂直大小 CV.CC_STAT_TOP: 连接组件的总面积(以像素为单位) 可以通过stats[label, column]访问 centroids: 具有每个质心的x和y位置的矩阵。此矩阵中的行对应于标签号。 ''' print(ret) # print(labels) # print(labels[2]) print(stats.shape) # print(centroids) #定义停止和细化角点的标准 criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 100, 0.001) corners = cv.cornerSubPix(gray, np.float32(centroids), (5, 5), (-1, -1), criteria) ''' cornerSubPix(image, corners, winSize, zeroZone, criteria) image: 8位单通道的灰度图像。 corners: 为整数值的像素位置 winSize: 指定了等式产生的窗口尺寸。 zeroZone: 定义了一个禁区(与win相似,但通常比win小),这个区域在方程组以及自相关矩阵中不被考虑。设置(-1,-1)表示不需要这个区域 criteria: 终止条件。可以是最大迭代次数cv.TERM_CRITERIA_MAX_ITER,或者设定的精度cv.TERM_CRITERIA_EPS类型,或者两者的组合。 ''' print(corners) res = np.hstack((centroids, corners)) res = np.int0(res) print(res) img[res[:, 1], res[:, 0]] = [0, 0, 255] img[res[:, 3], res[:, 2]] = [0, 255, 0] cv.imwrite('img/subpixel2.png', img) cv.waitKey(0) cv.destroyAllWindows()