一、使用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语言实现笔记(三)的更多相关文章

  1. OpenCV3计算机视觉Python语言实现笔记(四)

    1. Canny边缘检测 OpenCV提供了Canny函数来识别边缘.Canny边缘检测算法有5个步骤:使用高斯滤波器对图像进行去噪.计算梯度.在边缘上使用非最大抑制(NMS).在检测到的边缘上使用双 ...

  2. OpenCV3计算机视觉Python语言实现笔记(二)

    1. 图像与原始字节之间的转换 从概念上讲,一个字节能表示0到255的整数.目前,对于多有的实时图像应用而言,虽然有其他的表示形式,但一个像素通常由每个通道的一个字节表示. 一个OpenCV图像是.a ...

  3. OpenCV3计算机视觉Python语言实现笔记(五)

    图像的几何变换主要包括:平移.扩大与缩小.旋转.仿射.透视等等.图像变换是建立在矩阵运算基础上的,通过矩阵运算可以很快的找到对应关系. 1. 图像的平移 图像的平移,沿着x方向tx距离,y方向ty距离 ...

  4. OpenCV3计算机视觉Python语言实现笔记(一)

    Python3下OpenCV的安装 :http://blog.csdn.net/lwplwf/article/details/61616493 1. 读/写图像文件 OpenCV的imread()函数 ...

  5. 《OpenCV3 计算机视觉--Python语言实现 第二版》源代码及纠错

    1.源代码下载地址 <OpenCV3 计算机视觉--Python语言实现 第二版>由我们翻译,英文书名<Learning OpenCV3 Computer Vision with P ...

  6. Go语言学习笔记三: 常量

    Go语言学习笔记三: 常量 定义常量 常量就是在声明后不能再修改的量. const x int = 100 const y string = "abc" const z = &qu ...

  7. 【原】Learning Spark (Python版) 学习笔记(三)----工作原理、调优与Spark SQL

    周末的任务是更新Learning Spark系列第三篇,以为自己写不完了,但为了改正拖延症,还是得完成给自己定的任务啊 = =.这三章主要讲Spark的运行过程(本地+集群),性能调优以及Spark ...

  8. SM3杂凑算法Python语言实现——第三部分

    SM3杂凑算法实现--第三部分 一.SM3 密码概述        我们首先把需要用到的算法呈现出来,最后我们再考虑如何集合为一个库的方法,这一部分我们就开始编写一个新的算法:国家商用密码标准SM3密 ...

  9. 学习CV:《OpenCV 3计算机视觉Python语言实现第2版》中文PDF+英文PDF+代码

    理解与计算机视觉相关的算法.模型以及OpenCV 3 API背后的基本概念,有助于开发现实世界中的各种应用程序(比如:安全和监视领域的工具). OpenCV 3是一种先进的计算机视觉库,可以用于各种图 ...

随机推荐

  1. BZOJ1007: [HNOI2008]水平可见直线(单调栈)

    Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 8638  Solved: 3327[Submit][Status][Discuss] Descripti ...

  2. cf1132E. Knapsack(搜索)

    题意 题目链接 Sol 看了status里面最短的代码..感觉自己真是菜的一批..直接爆搜居然可以过?..但是现在还没终测所以可能会fst.. #include<bits/stdc++.h> ...

  3. 被低估的.net(中) - 广州.net俱乐部2019年纲领

    这是被低估的.net系列的中篇.上篇在这里:被低估的.net(上) - 微软MonkeyFest 2018广州分享会活动回顾 中篇本来不是这样的,中篇的草稿大纲其实在写上篇之前就写好了,嗯,当时给张队 ...

  4. 自定义控件详解(六):Paint 画笔MaskFilter过滤

    首先看一个API:setMaskFilter(MaskFilter maskfilter): 设置MaskFilter,可以用不同的MaskFilter实现滤镜的效果,如滤化,立体等. 以下有两个Ma ...

  5. 在a标签内添加hover样式的方法:

    <a href="javascript:void(0);" onmouseover="this.style.color='yellow';" onmous ...

  6. 键盘ascll码表

    键盘ascll码表-自用

  7. Django+MongoDB批量插入数据

    在百万级和千万级数据级别进行插入,pymongo的insert_many()方法有着很强的优势.原因是每次使用insert_one()方法进行插入数据,都是要对数据库服务器进行一次访问,而这样的访问是 ...

  8. [Hive_add_8] Hive 常用参数配置

    0. 说明 记录 Hive 常用参数的配置 1. 设置本地模式 让 Hive 自动使用 Hadoop 的本地模式运行作业,提升处理性能 适合小文件,一般用于测试 set hive.exec.mode. ...

  9. [福大软工] Z班 第7次成绩排行榜

    作业要求 http://www.cnblogs.com/easteast/p/7668887.html 评分细则 本次作业评分较为简单,只包含了两个方面的得分,一个是团队任务的计划(10'),一个是采 ...

  10. ABAP 7.50 新特性 – Open SQL中的宿主表达式和其它表达式

    在长期的停滞后,Open SQL的发展终于从沉睡中醒来.从ABAP 7.40开始,SAP推进了某些关键的改变,以尽可能地包含SQL92中的特性,并提供与ABAP CDS中的DDL里面的SELECT一样 ...