声音可能不太好听,是用 TTS 生成的。

使用一个固定窗口在图像上进行任意方向上的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,

都有着较大灰度变化,那么我们就可以认为该窗口中存在角点。举个例子,下图中 $A$ 是角点,$B$ 不是角点,如果用一个小窗口(蓝色)在点 $A$

处滑动,无论朝哪个方向走,窗口内的像素值都会发生明显的变化,比如窗口往左,那白色像素就越多,红色越少;但是对于 $B$ 点,无论朝哪

个方向滑动,窗口内的像素基本不变。

进一步地

基本数学公式如下:

$$E(u,v) = \sum_{(x,y) \in W}^{}W(x,y)\left [ I(x+u,y+v) - I(x,y) \right ]^{2}$$

其中 $w(x, y)$ 表示移动窗口,$I(x, y)$ 表示像素灰度值强度,范围为 $0-255$,$x,y$ 表示窗口内的像素坐标,$u,v$ 表示方向。

函数 $E(u,v)$ 是和图像一个窗口区域一一对应的,即首先需要用 $W(x,y)$ 确定一个窗口,然后再计算这个图像区域对应的 $E(u,v)$

函数来判断该窗口内是否存在角点。

$$I(x+u,y+u) = I(x,y) + uI_x(x,y) + vI_y(x,y) + R_n$$

去掉高阶项,原式近似为

$$E(u,v) \approx \sum_{(x,y) \in W}^{}W(x,y)\left [ uI_x(x,y) + vI_y(x,y) \right ]^{2}

= \sum_{(x,y) \in W}^{}W(x,y) \left (u^2I_x^2 + 2uvI_xIy + v^2I_y^2 \right ) \\

= \sum_{(x,y) \in W}^{}W(x,y)\begin{bmatrix}

u & v

\end{bmatrix}\begin{bmatrix}

I_x^2 & IxIy\\

IxIy & I_y^2

\end{bmatrix}\begin{bmatrix}

u \\

v

\end{bmatrix} \\

= \begin{bmatrix}

u & v

\end{bmatrix}\left (\sum_{(x,y) \in W}^{}W(x,y)\begin{bmatrix}

I_x^2 & IxIy\\

IxIy & I_y^2

\end{bmatrix} \right ) \begin{bmatrix}

u \\

v

\end{bmatrix} \\

=

\begin{bmatrix}

u & v

\end{bmatrix}M \begin{bmatrix}

u \\

v

\end{bmatrix}$$

每个实对称矩阵累加之后还是一个实对称矩阵,所以得到的 $M$ 是一个实对称矩阵。进一步有:

$$E(u,v) \approx \begin{bmatrix}

u & v

\end{bmatrix}P\begin{bmatrix}

\lambda_1 & \\

& \lambda_2

\end{bmatrix}P^T \begin{bmatrix}

u \\

v

\end{bmatrix} \\

= \begin{bmatrix}

u & v

\end{bmatrix}P\begin{bmatrix}

\lambda_1 & \\

& \lambda_2

\end{bmatrix} \left (\begin{bmatrix}

u & v

\end{bmatrix}P \right )^T \\

= \begin{bmatrix}

u^{'} & v^{'}

\end{bmatrix}\begin{bmatrix}

\lambda_1 & \\

& \lambda_2

\end{bmatrix} \begin{bmatrix}

u^{'} \\ v^{'}

\end{bmatrix} \\

= \lambda_1u^{'2} + \lambda_2v^{'2} \\

= \frac{u^{'2}}{1/\lambda_1} + \frac{v^{'2}}{1/\lambda_2}$$

可以看出函数 $E(x,y)$ 在 $xoy$ 平面的等高线就是椭圆。

我们的目标是:无论 $u,v$ 取什么值,或者说窗口 $w$ 无论沿哪个方向运动,$E(u,v)$ 都要尽可能地大。这样才符合角点的性质。

也就是说如果一个区域存在角点,那么相比与其它区域,相同的高度对应的等高线(椭圆)越小。

所以分母要尽可能地小,即特征值 $\lambda_1,\lambda_2$ 要尽可能地大。

当 $\lambda_1 >> \lambda_2$ 或 $\lambda_2 >> \lambda_1$ 时,检测到的就是边;当 $\lambda_1,\lambda_2$ 都很小,$E$ 接近常数,检查测到的是平坦区域;两个都很大,

并且近似一样大时,检测到的就是角点。引入一个量化的指标来衡量这种关系:

$$R = \det M - k(trace \; M) = \lambda_1\lambda_2 - \left ( \lambda_1 + \lambda_2 \right )$$

代码实现过程主要在于求得矩阵 $M$,即

$$M = \left (\sum_{(x,y) \in W}^{}w(x,y)\begin{bmatrix} I_x^2 & IxIy\\  IxIy & I_y^2 \end{bmatrix} \right )$$

假设窗口大小为 $5 \times 5$,即

$$W = \begin{bmatrix}

w_{11} & w_{12} & w_{13} & w_{14} & w_{15} \\

w_{21} & w_{22} & w_{23} & w_{24} & w_{25} \\

w_{31} & w_{32} & w_{33} & w_{34} & w_{35} \\

w_{41} & w_{42} & w_{43} & w_{44} & w_{45} \\

w_{51} & w_{52} & w_{53} & w_{54} & w_{55}

\end{bmatrix}$$

那么矩阵 $M$ 可以表示为

$$M = \begin{bmatrix}

w_{11}I_x^2 & w_{11}I_xI_y \\

w_{11}I_xI_y & w_{11}I_y^2

\end{bmatrix} + \begin{bmatrix}

w_{12}I_x^2 & w_{12}I_xI_y \\

w_{12}I_xI_y & w_{12}I_y^2

\end{bmatrix} + \cdots + \begin{bmatrix}

w_{55}I_x^2 & w_{55}I_xI_y \\

w_{55}I_xI_y & w_{55}I_y^2

\end{bmatrix}$$

因为不好表示,所以这里每个矩阵内都写成了 $I_x,I_y$,但它们是不同的,表示图像对应窗口元素的梯度值。

就看 $M[0][0]$ 这个元素,发现其实它就是矩阵 $W$ 和矩阵 $I_x$ 在相同窗口位置的卷积值。用一个 $5 \times 5$ 的高斯核作为 $W$ 矩阵。

代码如下:

#!/usr/bin/env python3

# -*- coding:utf8 -*-

import math

import cv2

import numpy as np

def Conv2D(kernel, img, padding, strides=(1, 1)):

"""

单通道图像卷积

"""

padImg = np.pad(img, padding, "edge")

result = []

for i in range(0, padImg.shape[0] - kernel.shape[0] + 1, strides[0]):

result.append([])

for j in range(0, padImg.shape[1] - kernel.shape[1] + 1, strides[1]):

val = (kernel * padImg[i:i + kernel.shape[0], j:j + kernel.shape[1]]).sum()

result[-1].append(val)

return np.array(result)

def Map2Gray(data):

"""

将数组中的元素映射到[0,255]区间

"""

maxVal = np.max(data)

minVal = np.min(data)

interval = maxVal - minVal

data = np.floor(255 / interval * (data - minVal))

return data

def CalImgGrad(f):

"""

用 5x5 sobel kernel 计算每个像素点的梯度

"""

sobelx = np.array([

[2, 1, 0, -1, -2],

[2, 1, 0, -1, -2],

[4, 2, 0, -2, -4],

[2, 1, 0, -1, -2],

[2, 1, 0, -1, -2]

])

sobely = np.array([

[2, 2, 4, 2, 2],

[1, 1, 2, 1, 1],

[0, 0, 0, 0, 0],

[-1, -1, -2, -1, -1],

[-2, -2, -4, -2, -2]

])

fx = Conv2D(sobelx, f, ((2, 2), (2, 2)))

fy = Conv2D(sobely, f, ((2, 2), (2, 2)))

fx2 = fx * fx

fy2 = fy * fy

fxfy = fx * fy

return fx2, fy2, fxfy

def CalRvals(fx2, fy2, fxfy):

"""

计算每个像素对应的M矩阵和R值

"""

W = 1.0 / 159 * np.array([

[2, 4, 5, 4, 2],

[4, 9, 12, 9, 4],

[5, 12, 15, 12, 5],

[4, 9, 12, 9, 4],

[2, 4, 5, 4, 2]

])

k = 0.05

fx2 = Conv2D(W, fx2, ((2, 2), (2, 2)))

fy2 = Conv2D(W, fy2, ((2, 2), (2, 2)))

fxfy = Conv2D(W, fxfy, ((2, 2), (2, 2)))

result = []

maxEValue = [] # 存储最大特征值

minEValue = [] # 存储最小特征值

for i in range(fx2.shape[0]):

result.append([])

maxEValue.append([])

minEValue.append([])

for j in range(fx2.shape[1]):

M = np.array([

[fx2[i, j], fxfy[i, j]],

[fxfy[i, j], fy2[i, j]]

])

a = np.linalg.det(M)

b = np.trace(M)

"""

M是实对称矩阵,按理必然存在实际特征值,可能由于精度缺失,

方程 x^2 - bx + a = 0 未必有解,所以 b ** 2 - 4 * a 取了个绝对值,

这样算出来的值就不对。

"""

delta = math.sqrt(math.fabs(b ** 2 - 4 * a))

e1 = 0.5 * (b - delta)

e2 = 0.5 * (b + delta)

r = a - k * b

result[-1].append(r)

maxEValue[-1].append(max(e1, e2))

minEValue[-1].append(min(e1, e2))

g1 = Map2Gray(np.array(maxEValue)) # 最大特征值图

g2 = Map2Gray(np.array(minEValue)) # 最小特征值图

g3 = Map2Gray(np.array(result).copy()) # R图

cv2.imshow('eMax', g1)

cv2.waitKey(0)

cv2.imshow('eMin', g2)

cv2.waitKey(0)

cv2.imshow('R', g3)

cv2.waitKey(0)

cv2.destroyAllWindows()

return np.array(result), g1, g2, g3

def Sign(img, rVals):

threshold = 25 * math.fabs(rVals.mean())

judge = rVals >= threshold

rectangle = (12, 12) # 标记矩形大小

thickness = 2 # 标记矩形边的厚度

for i in range(img.shape[0]):

for j in range(img.shape[1]):

up = max(i - rectangle[0] // 2, 0)

bottom = min(i + rectangle[0] // 2, img.shape[0] - 1)

left = max(j - rectangle[1] // 2, 0)

right = min(j + rectangle[1] // 2, img.shape[0] - 1)

# 为了使矩形框不发生重叠需要进行非极值抑制

isLocalExtreme = rVals[i,j] >= rVals[up:bottom + 1, left:right + 1]

if judge[i, j] and isLocalExtreme.all():

cv2.rectangle(img, (left, up), (right, bottom), (0, 0, 255), thickness)

return img

def HarrisCornerDetection(img):

grayImg = img.mean(axis=-1) # 变成单通道灰度图像

fx2, fy2, fxfy = CalImgGrad(grayImg)

rVals, g1, g2, g3 = CalRvals(fx2, fy2, fxfy)

finalImg = Sign(img, rVals)

return finalImg, g1, g2, g3

# =============================================================================

def RecordVideo(fullFileName):

fps = 25

size = (640, 480)

duration = 10 # 修改录制时长,单位s

frameCount = duration * fps

cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) # 打开摄像头

videoWriter = cv2.VideoWriter(fullFileName, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), fps, size)

print("Begin to record %ss video" % str(duration))

success, frame = cap.read()

while success and frameCount > 0:

videoWriter.write(frame)

success, frame = cap.read()

frameCount -= 1

cap.release()

print("End of recording")

def TestVideo():

fullFileName = "video.avi"

RecordVideo(fullFileName)

triggerCount = 0

capVideo = cv2.VideoCapture(fullFileName)

fps = capVideo.get(cv2.CAP_PROP_FPS)

frameInterval = int(1000 // fps) # ms

print()

print("Begin to playback video")

ret, videoFrame = capVideo.read()

while ret:

cv2.imshow('image', videoFrame)

flag = cv2.waitKey(frameInterval)

if flag == ord(' '):

triggerCount += 1

print("[%s]st trigger detection" % str(triggerCount))

cv2.destroyAllWindows()

finalImg, g1, g2, g3 = HarrisCornerDetection(videoFrame)

cv2.imshow('image', finalImg)

cv2.waitKey(0)

cv2.imwrite("[%s]-e-max.jpg" % str(triggerCount), g1)

cv2.imwrite("[%s]-e-min.jpg" % str(triggerCount), g2)

cv2.imwrite("[%s]-R.jpg" % str(triggerCount), g3)

cv2.imwrite("[%s]-final.jpg" % str(triggerCount), finalImg)

ret, videoFrame = capVideo.read()

capVideo.release()

cv2.destroyAllWindows()

print("End of playing")

def TestImage(fullFileName):

img = cv2.imread(fullFileName)

finalImg, g1, g2, g3 = HarrisCornerDetection(img)

cv2.imshow('image', finalImg)

cv2.waitKey(0)

cv2.destroyAllWindows()

TestVideo()

# TestImage("2.jpg")

java harris corner_Harris Corner Detection相关推荐

  1. Python+OpenCV:图像Harris角点检测(Harris Corner Detection)

    Python+OpenCV:图像Harris角点检测(Harris Corner Detection) 理论 corners are regions in the image with large v ...

  2. OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()

    OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack() 参考博客: Harris角点检测原理详解 Harri ...

  3. 巩膜:论文翻译《一种改进的眼角检测算法》An Improved Algorithm for Eye Corner Detection

    1509.04887.pdf论文翻译 An Improved Algorithm for Eye Corner Detection Anirban Dasgupta, Anshit Mandloi, ...

  4. OpenCV——角点检测 (Corner Detection)

    角点 角点通常被定义为两条边的交点,或者说,角点的局部邻域应该具有两个不同区域的不同方向的边界.角点检测(Corner Detection)是计算机视觉系统中获取图像特征的一种方法,广泛应用于运动检测 ...

  5. Python+OpenCV:图像快速角点检测算法(FAST Algorithm for Corner Detection)

    Python+OpenCV:图像快速角点检测算法(FAST Algorithm for Corner Detection) 理论 Feature Detection using FAST Select ...

  6. 2020cvpr-Correlation-Guided Attention for Corner Detection Based Visual Tracking

    https://www.bilibili.com/read/cv6647311/ 论文阅读之2020cvpr-Correlation-Guided Attention for Corner Detec ...

  7. java harris corner_CV算法:Harris角点(Harris Corner Detector)

    参考资料 Harris Corner Detector 斯坦福CS131-1718作业3 cornell-CS4670-5670-2016spring lec10_features2_web-Harr ...

  8. Harris 角点检测(Harris Corner Detection)(OpenCV实现)

    匹配问题 Harris角点检测是Chris Harris和Mike Stephens在1988年提出的.主要用于运动图像的追踪.当时的普遍想法是利用边缘进行追踪,但是当相机或物体运动时你不知道朝哪个方 ...

  9. 3d点云处理--特征点提取

    特征点提取思路: Handcrafted Harris family Harris 3D Harris 5D ISS Deep Learning USIP 特征点的描述方法较多. 直接的icp,ndt ...

  10. Harris Corner(Harris角检测)

    一.引言:关于兴趣点(interest points) 在图像处理和与计算机视觉领域,兴趣点(interest points),或称作关键点(keypoints).特征点(feature points ...

最新文章

  1. 算法理解|从头开始理解梯度提升算法
  2. ssh2 文件服务器,使用Node.js和SSH2从SFTP服务器读取文件
  3. SDN和OpenFlow的区别—Vecloud微云
  4. Swift UIlabel 的高级用法,文本显示表情,图片
  5. 自己写一个H5项目CI系统
  6. ThriftParserError: ThriftPy does not support generating module with path in protocol 'd'
  7. 创建构建方法android,如何快速创建并发布一个 Android 库
  8. 关于socket组播和ssdp(一)[修改1.2]
  9. 数据结构与算法(C语言版)——陈越
  10. FPGA中for语句描述的七人投票表决器
  11. MTK平台APN的配置
  12. IC卡、ID卡、CPU卡、RFID、NFC大致区分一览表
  13. 论文参考文献格式及意义
  14. php球半径为2的圆面积,某竖直平面内有一半径为R的光滑固定圆环,斜边长2R、短边长R的匀质直角三角板放在环内,试求三角板在其平衡位...
  15. 又一家硅谷巨头掀裁员潮!员工称像经历一场“屠杀”
  16. sstream类的详解
  17. 时序分析(8) -- GARCH(p,q)模型
  18. STM32F0-DAY1
  19. 一次ES性能优化,我发现了搞大数据的真相……
  20. 2014一年开发技术资料收藏整理(一)

热门文章

  1. MapReduce计算模型(二)
  2. 1040 有几个PAT
  3. 目标检测回归损失函数总结
  4. 【Rollo的Python之路】Python 队列 学习笔记 queue
  5. scrapy数据存储在mysql数据库的两种方式
  6. 两个辅助指针变量挖字符串
  7. http请求与响应(content-type)
  8. 【LeetCode】64. Minimum Path Sum
  9. Macbook Pro 使用小记
  10. leetcode刷题日记-边界着色