OpenCV3计算机视觉Python语言实现笔记(三)
一、使用OpenCV处理图像
1.不同颜色空间的转换
OpenCV中有数百种关于在不同色彩空间之间转换的方法。当前,在计算机视觉中有三种常用的色彩空间:灰度、BGR以及HSV(Hue, Saturation, Value)
灰度色彩空间是通过去除彩色信息来将其转换为灰阶,灰度色彩空间对中间处理特别有效,比如人脸检测。
BGR,即蓝-绿-红色彩空间,每一个像素点都由一个三元数组来表示,分别代表蓝、绿、红三种颜色。
HSV,H(Hue)是色度,S(Saturation)是饱和度,V(value)表示黑暗的程度(或光谱另一端的明亮程度)。
BGR的简短说明:当第一次处理BGR色彩空间时,可以不要其中的一个色彩分量,比如像素值[0, 255, 255](没有蓝色,绿色分量取最大值,红色分量取最大值)表示黄色。
2. 傅里叶变换
NumPy有快速傅里叶变换(FFT)的包,它包含了fft2()函数,该函数可以计算一幅图像的离散傅里叶变换(DFT)。
下面通过傅里叶变换来介绍图像的幅度谱。图像的幅度谱是另一种图像,幅度谱图像呈现了原始图像在变换方面的一种表示:把一幅图像中最明亮的像素放到图像中央,然后逐渐变暗,在边缘上的像素最暗。这样可以发现图像中有多少亮的像素和暗的像素,以及它们分布的百分比。傅里叶变换的概念是边缘检测或线段和形状检测等图像处理操作的基础。
2.1 高通滤波器
高通滤波器(HPF)是检测图像的某个区域,然后根据像素与周围像素的亮度差值来提升(boost)该像素的亮度的滤波器。
核是指一组权重的集合,它会应用在源图像的一个区域,并由此生成目标图像的一个像素。比如,大小为7的核意味着每49(7 x 7)个源图像的像素会产生目标图像的一个像素。可把核看作一块覆盖在源图像上可移动的毛玻璃片,玻璃片覆盖区域的光线会按某种方式进行扩散混合后透过去。以如下的核(kernal)为例:
[[0, -0.25, 0],
[-0.25, 1, -0.25],
[0, -0.25, 0]]
在计算完中央像素与周围邻近像素的亮度差值之和以后,如果亮度变化很大,中央像素的亮度会增加(反之则不会)。换句话说,如果一个像素比它周围的像素更突出,就会提升它的亮度。这在边缘检测上尤其有效,它会采用一种称为高频提升滤波器(high boost filter)的高通滤波器。
高通和低通滤波器都有一个称为半径(radius)的属性,它决定了多大面积的邻近像素参与滤波计算。下面是一个高通滤波器的例子。
import cv2
import numpy as np
from scipy import ndimage
kernal_3x3 = np.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
kernal_5x5 = np.array([[-1, -1, -1, -1, -1],
[-1, 1, 2, 1, -1],
[-1, 2, 4, 2, -1],
[-1, 1, 2, 1, -1],
[-1, -1, -1, -1,-1]])
# 使用函数cv2.imread() 读入图像。这幅图像应该在此程序的工作路径,或者给函数提供完整路径,第二个参数是要告诉函数应该如何读取这幅图片。 # • cv2.IMREAD_COLOR:读入一副彩色图像。图像的透明度会被忽略,这是默认参数。
# • cv2.IMREAD_GRAYSCALE:以灰度模式读入图像
img = cv2.imread('LENA256.bmp',0) # 注:此处后面要加上0,表示已灰度模式读入图像
k3 = ndimage.convolve(img, kernal_3x3) # 注:使用ndimage.convolve()时,滤波核的维度应与原始图像的维度相同,故此采用灰度图
k5 = ndimage.convolve(img, kernal_5x5) blurred = cv2.GaussianBlur(img, (11, 11), 0)
g_hpf = img - blurred
cv2.imshow("image", img)
cv2.imshow("3x3", k3)
cv2.imshow("5x5", k5)
cv2.imshow("g_hpf", g_hpf)
cv2.waitKey()
cv2.destroyAllWindows()
注:这些滤波器中的所有值加起来为0.
运行结果为:
导入模块之后,我们定义一个3x3和一个5x5的核,然后将读入的图像转换为灰度格式。通常大多数的图像处理会用NumPy来完成,但是这里的情况比较特殊,因为需要用一个给定的核与图像进行“卷积”(convolve),但是NumPy碰巧只接受一维数组。ndimage的convolve()函数支持经典的NumPy数组,cv2模块用这种数组来存储图像。
还有一种方法可实现高通滤波器:通过对图像应用低通滤波器之后,与原始图像计算差值。
2.2 低通滤波器
高通滤波器是根据像素与邻近像素的亮度差值来提升该像素的亮度。低通滤波器(Low Pass Filter, LPF)则是在像素与周围像素的亮度差值小于一个特定值时,平滑该像素的亮度。它主要用于去噪和模糊化,比如说,高斯模糊是最常用的模糊滤波器(平滑滤波器)之一,它是一个削弱高频信号信息强度的低通滤波器。
3. 边缘检测
OpenCV提供了许多边缘检测滤波函数,包括Laplacian()、Sobel()以及Scharr()。这些滤波函数都会将非边缘区域转为黑色,将边缘区域转为白色或其他饱和的颜色。但是,这些函数都很容易将噪声错误地识别为边缘。缓解这个问题的方法是在找到边缘之前对图像进行模糊处理。OpenCV也提供了许多模糊滤波函数,包括blur()(简单的算术平均)、medianBlur()以及GaussianBlur()。边缘检测滤波函数和模糊滤波函数的参数有很多,但总会有一个ksize参数,它是一个奇数,表示滤波器的宽和高(以像素为单位)。
这里使用medianBlur()作为模糊函数,它对去除数字化的视频噪声非常有效,特别是去除彩色图像的噪声;使用Laplacian()作为边缘检测函数,它会产生明显的边缘线条,灰度图像更是如此。在使用medianBlur()函数之后,将要使用Laplacian()函数之前,需要将图像从BGR色彩空间转为灰度色彩空间。
在得到Laplacian()函数的结果之后,需要将其转换成黑色边缘和白色背景的图像。然后将其归一化(使它的像素值在0到1之间),并乘以源图像以便能将边缘变黑。
注意,核的大小可由strokeEdges()函数的参数来指定。blurKsize参数会 作为medianBlur()含糊的ksize参数,edgeKsize参数会作为Laplacian()函数的ksize参数。对于作者的摄像头,将blurKsize值设为7,将edgeKsize值设为5会得到最好的效果。但对于较大的ksize(比如7),使用medianBlur()的代价很高。如果在使用strokeEdges()函数时遇到性能问题,可试着减小blurKsize的值。要关闭模糊效果,可以将blurKsize的值设为3以下。
4. 用定制内核做卷积
OpenCV预定义的许多滤波器(滤波函数)都会使用核。其实核是一组权重,它决定如何通过邻近像素点来计算新的像素点。核也称为卷积矩阵,它对一个区域的像素做调和(mix up)或卷积运算。通常基于核的滤波器(滤波函数)被称为卷积滤波器(滤波函数)。
OpenCV提供了一个非常通用的filter2D()函数,它运用由用户指定的任意核或卷积矩阵。卷积矩阵是一个二维数组,有奇数行、奇数列,中心的元素对应于感兴趣的像素。其他的元素对应于这个像素周围的邻近像素,每个元素都有一个整数或浮点数的值,这些值就是应用在像素值上的权重。如:
kernel = numpy.array([[-1, -1 , -1],
[-1, 9, -1],
[-1, -1, -1]])
其中感兴趣的像素权重为9,其邻近像素权重为-1。对感兴趣的像素来说,新的像素值使用当前像素值乘以9,然后减去8个邻近像素值。如果感兴趣的像素已经与其邻近像素有一点差别,那么这个差别会增加。这样会让图像锐化,因为该像素的值与邻近像素值之间的差距拉大了。注意权重加起来为1,如果不想改变图像的亮度就应该这样。如果稍微修改一下锐化核使它的权重加起来为0,就会得到一个边缘检测核,把边缘转为白色,把非边缘区域转为黑色。
在源图像和目标图像上分别使用卷积矩阵:cv2.filter2D(src, -1, kernel, dst). 第二个参数指定了目标图像每个通道的位深度(比如,位深度cv2.CV_8U表示每个通道为8位),如果为负值,则表示目标图像和源图像有同样的位深度。
注:对彩色图像来说,filter2D()会对每个通道都用同样的核。如果要对每个通道使用不同的核,就必须用split()函数和merge()函数。
对于模糊滤波器,为了达到模糊效果,通常权重和应该为1,而且邻近像素的权重全为正。
锐化、边缘检测以及模糊等滤波器都是用了高度对称的核。但是有时不对称的核也会得到一些有趣的效果。
# VConvolutionFilter 表示一般的滤波器
class VConvolutionFilter(object):
"""A filter that applies a convolution to V(or all of BGR).""" def __init__(self, kernel):
self._kernel = kernel def apply(self, src, dst):
"""Apply the filter with a BGR or gray source/destination."""
cv2.filter2D(src, -1, self._kernel, dst) # SharpenFilter 表示特定的锐化滤波器
class SharpenFilter(VConvolutionFilter):
"""A sharpen filter with a 1-pixel radius."""
def __init__(self):
kernel = numpy.array([[-1, -1, -1],
[-1, 9, -1],
[-1, -1, -1]])
VConvolutionFilter.__init__(self, kernel) # 边缘检测滤波器
class FindEdgesFilter(VConvolutionFilter):
"""A edge-finding filter with a 1-pixel radius."""
def __init__(self):
kernel = numpy.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
VConvolutionFilter.__init__(self, kernel) # 邻近平均滤波器
class BlurFilter(VConvolutionFilter):
"""A edge-finding filter with a 1-pixel radius."""
def __init__(self):
kernel = numpy.array([[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04]])
VConvolutionFilter.__init__(self, kernel)
下面介绍一种核,它同时具有模糊(有正的权重)和锐化(有负的权重)的作用。这会产生一种脊状(ridge)或者浮雕(embossed)的效果。
class EmbossFilter(VConvolutionFilter):
"""A edge-finding filter with a 1-pixel radius.""" def __init__(self):
kernel = numpy.array([[-2, -1, 0],
[-1, 1, 1],
[0, 1, 2]])
VConvolutionFilter.__init__(self, kernel)
OpenCV3计算机视觉Python语言实现笔记(三)的更多相关文章
- OpenCV3计算机视觉Python语言实现笔记(四)
1. Canny边缘检测 OpenCV提供了Canny函数来识别边缘.Canny边缘检测算法有5个步骤:使用高斯滤波器对图像进行去噪.计算梯度.在边缘上使用非最大抑制(NMS).在检测到的边缘上使用双 ...
- OpenCV3计算机视觉Python语言实现笔记(二)
1. 图像与原始字节之间的转换 从概念上讲,一个字节能表示0到255的整数.目前,对于多有的实时图像应用而言,虽然有其他的表示形式,但一个像素通常由每个通道的一个字节表示. 一个OpenCV图像是.a ...
- OpenCV3计算机视觉Python语言实现笔记(五)
图像的几何变换主要包括:平移.扩大与缩小.旋转.仿射.透视等等.图像变换是建立在矩阵运算基础上的,通过矩阵运算可以很快的找到对应关系. 1. 图像的平移 图像的平移,沿着x方向tx距离,y方向ty距离 ...
- OpenCV3计算机视觉Python语言实现笔记(一)
Python3下OpenCV的安装 :http://blog.csdn.net/lwplwf/article/details/61616493 1. 读/写图像文件 OpenCV的imread()函数 ...
- 《OpenCV3 计算机视觉--Python语言实现 第二版》源代码及纠错
1.源代码下载地址 <OpenCV3 计算机视觉--Python语言实现 第二版>由我们翻译,英文书名<Learning OpenCV3 Computer Vision with P ...
- Go语言学习笔记三: 常量
Go语言学习笔记三: 常量 定义常量 常量就是在声明后不能再修改的量. const x int = 100 const y string = "abc" const z = &qu ...
- 【原】Learning Spark (Python版) 学习笔记(三)----工作原理、调优与Spark SQL
周末的任务是更新Learning Spark系列第三篇,以为自己写不完了,但为了改正拖延症,还是得完成给自己定的任务啊 = =.这三章主要讲Spark的运行过程(本地+集群),性能调优以及Spark ...
- SM3杂凑算法Python语言实现——第三部分
SM3杂凑算法实现--第三部分 一.SM3 密码概述 我们首先把需要用到的算法呈现出来,最后我们再考虑如何集合为一个库的方法,这一部分我们就开始编写一个新的算法:国家商用密码标准SM3密 ...
- 学习CV:《OpenCV 3计算机视觉Python语言实现第2版》中文PDF+英文PDF+代码
理解与计算机视觉相关的算法.模型以及OpenCV 3 API背后的基本概念,有助于开发现实世界中的各种应用程序(比如:安全和监视领域的工具). OpenCV 3是一种先进的计算机视觉库,可以用于各种图 ...
随机推荐
- 《JavaScript高级程序设计》笔记:在HTML中使用Javascript(二)
script元素 向html页面中插入js的主要方法就是使用<script>元素.使用<script>元素的方式有两种:直接在页面中嵌入js代码和包含外部js文件.直接在页面中 ...
- 一个AI产品经理怎么看AI的发展
一个AI产品经理怎么看AI的发展 https://www.jianshu.com/p/bed6b22ae837 最近一直在思考这个问题,人工智能接下来的几年会有什么样的发展,是否真的能够在很多工作岗位 ...
- 快速排序的java实现
快速排序也属于“交换”类的排序. 核心思想可以概括为:通过多次划分操作实现排序.每一趟选择当前所有子序列中的一个关键字(通常是第一个)作为枢轴,将小于它的元素统统放到它的前面,大于它的统统放到它的后面 ...
- js获取选中日期的当周的周一和周日
js获取选中日期的当周的周一和周日 第一种方法(推荐): function getWeekStr(str) { // 将字符串转为标准时间格式 str2 = Date.parse(str); let ...
- 2018-05-27-computer-using-hints-电脑使用帮助[持续更新]
layout: post title: 2018-05-27-computer-using-hints-电脑使用帮助 key: 20180527 tags: ubuntu cuda cudnn ten ...
- mssql 一次向表中插入多条数据的方法分享 (转自:http://www.maomao365.com/?p=6058)
转自:http://www.maomao365.com/?p=6058) <span style="font-size:16px;font-weight:bold;"> ...
- Asp.Net WebApi 项目及依赖整理
一.目前版本 Microsoft ASP.NET Web API 2.2 对应程序集版本5.2.3 二.默认生成的配置文件中的内容 <packages> <package id=&q ...
- AI学习---深度学习&TensorFlow安装
深度学习 深度学习学习目标: 1. TensorFlow框架的使用 2. 数据读取(解决大数据下的IO操作) + 神经网络基础 3. 卷积神经网络的学习 + 验证码识别的案例 机器学习与深度学 ...
- docker往阿里云推镜像和打包镜像
向仓库推镜像 1. 登录到阿里云docker镜像站点,然后创建仓库. 2.要按照阿里云官方给定的仓库名称来使用,所以我们一般都要继续给准备要上传的镜像二次添加标签,如下所示: 3.在终端登录阿里云站点 ...
- MATLAB简易画图
给定一组特殊点,连线作图 作者:凯鲁嘎吉 - 博客园 http://www.cnblogs.com/kailugaji/ 以成绩隶属函数为例: score.m cj_x1=[ 0.1]; cj_y1= ...