深度学习以外的视觉算法

尽管深度学习为基础的计算机视觉技术攻克了很多传统算法的难题,但了解这些传统的视觉算法依然是有必要的,因为它们提供了很多不同的理解计算机视觉的视角。并且相比于深度神经网络来说,计算机视觉的很多算法学起来还是很有挑战性的,但是如果你真正花时间去攻克它们,就会发现这些算法背后如此的巧夺天工,以至于你会由衷的为这些算法的发明者的智慧发出赞叹!

A lot many things look difficult and mysterious. But once you take the time to deconstruct them, the mystery is replaced by mastery and that is what we are after. If you are a beginner and are finding Computer Vision hard and mysterious, just remember the following

Q : How do you eat an elephant ?

A : One bite at a time!

Spacial Coherent Data

Computer Vision 这门学科处理的信号不仅仅包含传统意义上的相机产生的照片信息,还包括其他类型的传感器产生的信息,包括声学信息,这些信息在空间之内传播和变化,因此被称为 Spacial Coherent Data,通过对这些信息进行捕捉和感知,可以让机器获得空间感知能力。CV 的几个典型的应用场景包括自动驾驶、医学影像分析、图像标注和人脸识别等等。

Cognitive and Emotional Intelligence

认知智能 Cognitive Intelligence 即通常所说的 IQ,情感智能 Emotional Intelligence 即通常所说的 EQ,通过计算机视觉技术 Affectiva 使得计算机可以识别与之交互的人类的面部表情和肢体语言,进而了解此时与之交互的人的情感状态,从而建立更加丰富的情感交互能力。

计算机视觉应用的通用工作流

对于上述表情功能的实现,以及任何一个计算机视觉任务,通常都需要经过以下几个大致的过程:

输入数据的预处理:包括降噪、缩放、和变更颜色空间等,其最重要的目的在于对于多个输入图片的标准化 Standardization

定位目标区域:目标检测和图像分割,例如在情感识别中,需要定位面部重要的特征点

特征提取:提取特征数据,例如下文中提到的 HOG,FAST 等

目标识别:对于新的输入执行目标识别和特征匹配,进而对于被检测的对象的状态给予一个预测

图像的表征

在计算机的世界里,图像通常被表示为一系列的网格状的数字(像素)矩阵,这一表示形式是大多数图像处理技术的基础。我们可以通过坐标位置来确定某个像素点的位置,并通过更改该点的像素的值来更改图像的显示样式。

色彩空间 Color Spaces

同人类理解世界一样,对于计算机来说同样有“知识的表示形式决定了学习的难易程度”,为了更好的表示图像信息,除了常用的 RGB 通道外,还有两种常用的颜色空间表示方法:

RGB:Red,Green,Blue,这个空间中的 RGB 分布取值范围都在 [0, 255],呈均匀分布

HSV: 色调 Hue,饱和度 Saturation,亮度 Value,这个空间中的颜色分布呈现为一个圆柱体,在不同的软件中这三者的取值范围不同,在使用中需要注意转换。在 OpenCV 中 Hue 通道的取值范围为 [0, 179],Saturation 通道的取值范围是 [0, 255],亮度 Value 通道的取值范围为 [0, 255]。由于色调通道在不同的光照条件下变化范围不大,而亮度通道则在不同的光照条件下变化明显,因此可以通过调整色调通道的值来更好的选择目标区域而避免光照条件的影响。

HLS:Hue, Lightness, Saturation

由于在大部分计算机视觉应用中,光照条件对于算法的识别能力是有影响的,因此后两种颜色空间表示方法考虑了亮度信息,因此可以用于图像的光照条件的分辨。

通过 OpenCV 将图片从 RGB 空间转到 HSV 空间的代码如下:

cv2.cvtColor(input_image, cv2.COLOR_BGR2HSV)

这里需要注意的是在 OpenCV 中默认的颜色顺序是 BGR 而非 RGB,如果需要做这一转换,则可以通过如下代码进行:

cv2.cvtColor(input_image, cv2.COLOR_BGR2RGB)

由于大部分人对于 RGB 空间的色彩更熟悉,所以如果想知道某一个 RGB 空间下的色彩对应的 HSV 的值,可以通过如下代码来实现:

green = np.uint8([[[0,255,0 ]]])

hsv_green = cv2.cvtColor(green, cv2.COLOR_BGR2HSV)

print(hsv_green)

目标区域的选取

在既定的色彩空间下,可以通过 cv2.inRange() 选择取值在一定范围内的像素来对目标区域进行选取,并且由于图像被以数组的形式进行存储,因此可以通过简单的数组加法来对多个图像进行叠加。由于纯色的背景更加容易通过这一操作来编辑,因此在 Udacity 的课程中讲者背后的背景通常都是蓝色的。

Space travelling Pizza

# Define the masked area

lower_blue = np.array([0, 0, 230])

upper_blue = np.array([50, 50, 255])

mask = cv2.inRange(image_copy, lower_blue, upper_blue)

# Mask the image to let the pizza show through

masked_image = np.copy(image_copy)

masked_image[mask != 0] = [0, 0, 0]

# Display it!

plt.imshow(masked_image)

边缘检测和图像信息的过滤

在图像中除了简单的 RGB 或 HSV 通道信息外,图像本身的模式变化也是一个非常有用的信息,例如我们在图像中看到的物体和背景的边缘 Edges,其最明显的特征就是边缘两侧具有明显的色彩强度 Intensity 变化。

Intensity is a measure of light and dark similar to brightness, and we can use this knowledge to detect other areas or objects of interest. For example, you can often identify the edges of an object by looking at an abrupt change in intensity which happens when an image changes from a very dark to light area.

进一步地,在很多情况下图像中的模式变化是有一定规律可循的,衡量这一变化模式的一个重要指标就是变化的频率,而研究频率最为有效的办法之一则是伟大的傅立叶变换。所谓的高频图像或者图像当中的高频部分就是指其强度数值变化频率较高的部分,而低频图像或者图片中的低频部分则是指图片上信息一致或者渐变的部分。

Similar to sound, frequency in images is a rate of change. But, what does it means for an image to change? Well, images change in space, and a high frequency image is one where the intensity changes a lot. And the level of brightness changes quickly from one pixel to the next. A low frequency image may be one that is relatively uniform in brightness or changes very slowly. Most images have both high-frequency and low-frequency components.

Fourier transform for images with different frequencies

The Fourier Transform (FT) is an important image processing tool which is used to decompose an image into its frequency components. The output of an FT represents the image in the frequency domain, while the input image is the spatial domain (x, y) equivalent. In the frequency domain image, each point represents a particular frequency contained in the spatial domain image. So, for images with a lot of high-frequency components (edges, corners, and stripes), there will be a number of points in the frequency domain at high frequency values.

通过傅立叶变换将图像上的信息分解为不同的频率组成部分之后,就可以为了过滤掉不需要的信息或者突出感兴趣的信息而使用不同类型的滤波器 Filter 来对图像进行处理。

在图像处理的语境中,高通滤波器 High-pass filter 的目的在于锐化 Sharpen 图像中的高频部分,其通过类似 Sobel 滤波器(每一个滤波器只检测一个方向的边缘)这样的边缘检测卷积核来实现。而低通滤波器则主要用于降噪 Denoising 或图像模糊 Blur,其通过平均化卷积核区域内的所有像素的信息,如 Gaussian Blur 来实现。

# High pass filter further intensify the center element if it already stand out

# All elements should add up to 0

high_pass = np.array([[-1, -1, -1],

[-1, 8, 1],

[-1, -1, -1]])

high_pass

array([[-1, -1, -1],

[-1, 8, 1],

[-1, -1, -1]])

# Low pass filter averaging and smoothing the target area

low_pass = np.ones((3, 3)) / 9

low_pass

array([[ 0.11111111, 0.11111111, 0.11111111],

[ 0.11111111, 0.11111111, 0.11111111],

[ 0.11111111, 0.11111111, 0.11111111]])

High pass filter will black out low frequency part of the image

我们所讲的滤波器 Filter 在很多情况下又被称为核 kernel,通过采用特定的核和滤波器对于图像进行过滤操作,可以突出图像中感兴趣的部分而忽略不感兴趣的部分。在实际使用中,通常先将图片进行低通滤波,再进行高通滤波以避免产生无意义的干扰信息 Noise。

MRI brain image processing

A kernel is a set of weights that are applied to a region in a source image to generate a single pixel in the destination image.

对于执行边缘检测的核(高通)来说,由于需要通过计算的结果来反应图像上每一个位置的强度变化情况,因此每一个核中的数字加总的结果应该是 0,此时如果在某一个位置得到的结果为 0,则意味这在这个地区没有强度变化,也即没有边缘过渡。核中的参数加总不为 0 的操作会对图像进行加亮或暗化。由计算过程可知,执行边缘检测的过滤计算的结果的大小即代表了核覆盖的区域内的边缘过渡是否强烈,结果越大则边缘越明显,而核中的数字也称为权重的原因正是其决定了相应位置的像素在最终计算结果中的权重值。

Canny Edge Detection

在边缘检测过程中,常见的两个问题是:

多大程度的强度改变应该被定义为一个边缘?

我们如何能够一致性的展示出细微和宽厚的边缘?

这就要求我们能够拥有更加高性能的边缘检测器 - Canny Edge Detection,其实现过程如下:

通过 Gaussian Blur 来完成低通滤波

通过多个 Sobel 滤波器来识别出边缘的粗细和方向

采用非极大抑制来分离出较粗的线条,并将它们以一个像素的宽度来重新展示,经过处理后的图像是一个 binary image

Use Hysteresis to isolate the best edges,在选择的过程中需要设定一个强度梯度的最小和最大的阈值,并且只保留处于最低阈值之上的与其他确定边缘连接的线条,以保留有意义的边界信息并去掉可能的噪声,其中阈值最小和最大的值的比例一般选择 1:2 或 1:3

How Hysteresis works

gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

lower = 100

upper = 300

edges = cv2.Canny(gray, lower, upper)

plt.imshow(edges, cmap='gray')

在建立的基本的边缘检测工具后,下一步就是要了解如果进一步地在图像中检测特定的形状。

Hough Transform

Hough Transform 是一个非常重要的形状检测工具,这个方法的实现原理比较复杂,尝试理解如下:

在直角坐标系下的一条直线可以被表示为 y = mx + b,相应的这条直线在极坐标系下则可以用一个点(ρ, θ)来表示,其中 ρ 代表原点到这条直线的距离,而 θ 则表示这条直线和 x 轴的夹角。并且对于指定的点 (x, y),如果再指定直线与坐标轴的夹角 θ,则 ρ 可以通过 ρ = xcosθ + ysinθ 来唯一确定。由于在直角坐标系下通过直线上某个点可以绘制出无数条直线,这些直线所对应的极坐标下的点则构成一条正弦曲线。在实际检测过程中,算法将建立一个二维的数组,称作 Accumulator,其横轴为 ρ ,纵轴为 θ,对于任意一个点 (x, y) 和它相邻的点,算法会计算是否在这个点附近有直线存在。

在实际使用中,在执行 Hough 变换之前需要将图像转化为灰度图像,并通过 Canny 边缘检测器进行滤波,函数的输入结果为 binary image。

gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

# Define our parameters for Canny

low_threshold = 50

high_threshold = 100

edges = cv2.Canny(gray, low_threshold, high_threshold)

# Parameters for Hough Transform

rho = 1

theta = np.pi/180

threshold = 60

min_line_length = 100

max_line_gap = 5

# Creating an image copy to draw lines on

line_image = np.copy(image)

# Run Hough on the edge-detected image

lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]),

min_line_length, max_line_gap)

# Iterate over the output "lines" and draw lines on the image copy

for line in lines:

for x1,y1,x2,y2 in line:

cv2.line(line_image, (x1, y1), (x2, y2), (255, 0, 0), 5)

plt.imshow(line_image)

Square detection with Hough Transformation

Haar Cascade Face Detection

Haar Cascade 算法通过一系列包含和不包含脸部的图片来完成训练,这个利用 Haar feature 进行脸部识别的算法在计算的过程中会逐步消除掉判断为非脸部的图片位置,进而减小检测范围,因此算法性能十分高效,可以实时进行面部检测。

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# load in cascade classifier

face_cascade = cv2.CascadeClassifier('detector_architectures/haarcascade_frontalface_default.xml')

# run the detector on the grayscale image

faces = face_cascade.detectMultiScale(gray, 4, 6)

img_with_detections = np.copy(image) # make a copy of the original image to plot rectangle detections ontop of

# loop over our detections and draw their corresponding boxes on top of our original image

for (x, y, w, h) in faces:

# draw next detection as a red rectangle on top of the original image.

# Note: the fourth element (255,0,0) determines the color of the rectangle,

# and the final argument (here set to 5) determines the width of the drawn rectangle

cv2.rectangle(img_with_detections, (x, y), (x+w, y+h), (255, 0, 0), 5)

Corner Detection

在很多情况下,图像中的成角部分能够提供很多特别有效的特征信息,在 OpenCV 中一个较为常用的方法是 cv2.cornerHarris。

gray = cv2.cvtColor(image_copy, cv2.COLOR_RGB2GRAY)

gray = np.float32(gray)

# Detect corners

dst = cv2.cornerHarris(gray, 2, 3, 0.04)

# Dilate corner image to enhance corner points

dst = cv2.dilate(dst, None)

# Try changing this free parameter, 0.1, to be larger or smaller ans see what happens

thresh = 0.1*dst.max()

# Create an image copy to draw corners on

corner_image = np.copy(image_copy)

# Iterate through all the corners and draw them on the image (if they pass the threshold)

for j in range(0, dst.shape[0]):

for i in range(0, dst.shape[1]):

if(dst[j,i] > thresh):

# image, center pt, radius, color, thickness

cv2.circle( corner_image, (i, j), 1, (0, 255, 0), 1)

plt.imshow(corner_image)

Harris Corner Detection

Image Segmentation

在完成了前述一系列的基本特征检测以后,一个重要的应用就是对图像进行分割,在图像分割之前需要进一步完成的是轮廓提取(在 OpenCV 中当背景是黑色,而物体是白色时最容易实现轮廓提取,这就是为何很多处理算法的结果都是 binary image)。

# Convert to grayscale

gray = cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)

# Create a binary thresholded image

retval, binary = cv2.threshold(gray, 225, 255, cv2.THRESH_BINARY_INV)

# Find contours from thresholded, binary image

retval, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Draw all contours on a copy of the original image

contours_image = np.copy(image)

contours_image = cv2.drawContours(contours_image, contours, -1, (0,255,0), 3)

plt.imshow(contours_image)

findContours and drawContours with openCV

参考阅读

计算机视觉知识表征,计算机视觉基础 - 边缘和轮廓检测相关推荐

  1. 边缘和轮廓检测——计算机视觉的应用

    计算机视觉的重点是从计算机中的视频和图像中提取有意义的信息.在本文中,我们将从初学者开始探索一个使用 OpenCV 的出色计算机视觉项目. 其标题是"使用计算机视觉进行边缘和轮廓检测&quo ...

  2. 计算机视觉OpenCV(五):图像金字塔与轮廓检测

    目录 图像金字塔 1. 高斯金字塔(Gaussian Pyramid) 2. 拉普拉斯金字塔(Laplacian Pyramid) 图像轮廓 1. 查找检测物体的轮廓 2. 绘制轮廓 3. 轮廓特征 ...

  3. 计算机视觉 什么是计算机视觉

    1.什么是计算机视觉? 作为人类,我们可以轻松地感知周围世界的三维结构.想想当你看着坐在你旁边桌子上的花瓶时,三维感知是多么生动.您可以通过在其表面上播放的微妙的光影图案来分辨每个花瓣的形状和半透明度 ...

  4. 1. 【Part3】 Contour Detection and Hierarchical Image Segmentation【轮廓检测图像分割】

    Reference from Arbelaez, P., Maire, M., Fowlkes, C., & Malik, J. (2011). Contour detection and h ...

  5. 1. 【Part2】 Contour Detection and Hierarchical Image Segmentation【轮廓检测图像分割】

    Reference from Arbelaez, P., Maire, M., Fowlkes, C., & Malik, J. (2011). Contour detection and h ...

  6. Opencv中的轮廓检测及应用

    在openCV中,我们可以对图片的轮廓进行检测,虽然轮廓的检测看起来很简单,只是对一个图形的边框进行描绘,但是,它在很多领域上都应用到了,例如:人脸识别.车辆检测.视频采集等,下面我会通过人脸识别和车 ...

  7. CV:计算机视觉技术之图像基础知识(二)—图像内核的可视化解释

    CV:计算机视觉技术之图像基础知识(二)-图像内核的可视化解释 目录 图像内核的可视化解释 测试九种卷积核 官方Demo DIY图片测试 DIY实时视频测试 相关文章 CV:计算机视觉技术之图像基础知 ...

  8. CV:计算机视觉技术之图像基础知识(二)—图像内核的九种卷积核可视化解释(blur/bottom sobel /emboss/identity /sobel /outline/sharpen)

    CV:计算机视觉技术之图像基础知识(二)-图像内核的九种卷积核可视化解释(blur/bottom sobel /emboss/identity /left sobel /outline/right s ...

  9. 计算机视觉知识基础_我见你:计算机视觉基础知识

    计算机视觉知识基础 My introduction to Computer Vision happened in 2017 when I was doing Self-driving Car Nano ...

最新文章

  1. php 判断是否有相同的ID,如果有就修改数据库字段,没有就插入数据库字段
  2. 粉丝们请注意!送款全新的AirPods Pro!
  3. php java memcached_php和java的memcached使用的兼容性问题解决过程
  4. 虚方法的使用 c# 1613719803
  5. 第十四节(接口(行为))
  6. 演示Go语言多返回值功能
  7. linux 内核 ide,Linux设备驱动程序学习(7)-内核的数据类型
  8. 为什么 Rust 连续 4 年获「最受喜爱编程语言」?
  9. Java-多线程第三篇3种创建的线程方式、线程的生命周期、线程控制、线程同步、线程通信...
  10. Python3爬取起点中文网阅读量信息,解决文字反爬~~~附源代码
  11. 打印照片显示rpc服务器,打印照片时出现了“RPC服务器不可用”的错误怎么办?...
  12. Progressive Layered Extraction (PLE)
  13. 成为虚无鸿蒙系统掌控者,飞剑问道:烟雨飞剑破开鸿蒙空间,秦云成第四位鸿蒙掌控者!...
  14. 2.灰尘对计算机的影响,灰尘对电脑有影响不?
  15. 【蓝队攻防演练思路】From 滴滴蓝军
  16. 知乎 | 大家都见过哪些让你虎躯一震的代码?
  17. google的视频下载插件
  18. 2022年最新浙江道路运输安全员真题题库及答案
  19. OSChina 周五乱弹 —— 终于发现红薯看片的证据了
  20. 03 分布式系统的技术栈

热门文章

  1. 词根词缀 (一):前缀篇
  2. python定时开关机的代码_python实现Windows电脑定时关机
  3. 嵌入式 Linux平台 C程序 交叉编译技术
  4. mysql数据库读取数据,教你如何从 MySQL 数据库读取数据
  5. 28岁的他如何从运营转岗产品经理
  6. 迅雷专用链接原理及转换
  7. 音视频开发四:FFmpeg音视频处理的基本命令使用
  8. CTFshow - 七夕杯复现
  9. python爬虫之Scrapy框架,基本介绍使用以及用框架下载图片案例
  10. EM算法·最大期望算法