本文的内容都与图像处理有关,这时需要修改图像,比如要使用具有艺术性的滤镜、外插(extrapolate)某些部分、分割、粘贴或其他需要的操作。

  1、不同色彩空间的的转换

    OpenCV有数百种关于在不同色彩空间之间转换的方法。当前,计算机视觉中有三种常用的色彩空间:灰度、BGR以及HSV(Hue,Saturation,Value)。

    灰度色彩空间是通过去除彩色信息来将其转换成灰阶,灰度色彩空间对中间处理特别有效,比如人脸检测。

    BGR,即蓝-绿-红色彩空间,每一个像素点都由一个三元数组来表示,分别代表蓝、绿、红三种颜色。

    HSV,H(Hue)是色调、S(Saturation)是饱和度、V(Value)表示黑暗的程度(或光谱另一端的明亮程度)。

    BGR的简短说明

    当第一次处理BGR色彩空间的时候,可以不要其中的一个色彩分量,比如像素值(0,255,255)(没有蓝色,绿色分量取最大值,红色分量取最大值)表示黄色,绿色和红色混合产生浑浊的褐色,

  这是因为计算所使用的颜色模型具有可加性并且处理的是光照,而绘画不是这样(它遵从建色模型(subtractive color model))。计算机使用显示器发光来做颜色的媒介,

  因此运行在计算机的软件所使用的色彩模型是加色模型。

  2、佛里叶变换

    在OpenCV中,对图像和视频的大多数处理都或多或少会涉及佛里叶变换的概念。Joseph Fourier(约瑟夫.佛里叶)是一位18实际的法国数学家,他发现并推广了很多数学概念,

  主要研究热学规律,在数学上,他认为一切都可以用波形来描述。具体而言,他观察到的所有波形都可以由一系列简单其频率不同的正弦曲线叠加得到。也就是说,

  人们看到的波形都是由其它波形叠加得到的。这个概念对操作图像非常有帮助,因为这样我们就可以区分图像里哪些区域的信号(比如图像像素)变化特别强,哪些区域的信号变化不那么强,

  从而可以任意地标记噪声区域、感兴趣区域、前景和背景等。原始图像有许多频率组成,人们能够分离这些频率来处理图像和提取感兴趣的数据。

    注意:在OpenCV环境中,有许多实现了算法让我们能够处理图像,理解图像中所包含的含义。这些算法在 NumPy中也有实现,而且更容易使用。NumPy有快速佛里叶变换(FFT)的包,

  它包含了fft2()函数,此函数可以计算一副图像的离散佛里叶变换(DFT)。

    下面通过介绍佛里叶变换来介绍图像的幅度谱(magnitude spectrum)。图像的幅度谱是另一种图像,幅度谱图像呈现了原始图像在变化方面的一种表示:把一副图像中最明亮的像素放到图中央,

  然后逐渐变暗,在边缘的像素最暗。这样可以发现图像中有多少亮的像素和暗的像素,以及他们分布的百分比。

    佛里叶变换的概念是许多常见的图像处理操作的基础,比如边缘检测或线段的和形状检测。

    下面先介绍两个概念:高通滤波器和低通滤波器,上面提到那些操作都是以这两个概念和佛里叶变换为基础。

  2.1、高通滤波器

    高通滤波器(High-pass filter:HPF)是监测图像的某个区域,然后根据像素与周围像素的亮度差值来提示(boost)该像素的亮度的滤波器。

    以如下的核(kernel)为例:

    注意:核是指一组权重的结合,它会应用在源图像的一个区域,并由此产生目标图像的一个像素。比如,大小为7的核意味着每49(7*7)个源图像的像素会产生目标图像的一个像素。

  可以把核看作一块覆盖在源图像上可以移动的毛玻璃片,玻璃片覆盖区域的光线会按某种方式进行扩散混合后投过去。

    在计算完中央像素和周围临近像素的亮度差值之和以后,如果亮度变化很大,中央像素的亮度会增加(反之则不会)。换句话说,如果一个像素比它周围的像素突出,就会提示它的高度。

  这在边缘检测上尤其有效,它会采用一种称为高频提示滤过器(high boost filger)的高通滤波器。

    高通和低通滤波器都有一个称为半径(radius)的属性,它决定了多大面积的临近像素参与滤波运算。

    下面是一个高通滤波器的例子:

import cv2
import numpy as np
import os
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]])
# 注意这些滤波器里面的值加起来等于0,以后会解释这个原因
# 使用函数cv2.imread() 读入图像。这幅图像应该在此程序的工作路径,或者给函数提供完整路径,第二个参数是要告诉函数应该如何读取这幅图片。 # • cv2.IMREAD_COLOR:读入一副彩色图像。图像的透明度会被忽略,这是默认参数。
# • cv2.IMREAD_GRAYSCALE:以灰度模式读入图像 img = cv2.imread('flower.jpg',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("flower", img)
cv2.imshow("flower:3x3", k3)
cv2.imshow("flower:5x5", k5)
cv2.imshow("flower:g_hpf", g_hpf)
cv2.waitKey()
cv2.destroyAllWindows()

  运行效果图如下:

  

    导入模块以后,我们定义了一个3*3和一个5*5的核,然后将读入的图像转换为灰度格式。通常大多数的图像处理会用NumPy来完成,但是这里的情况比较特殊,

  因为需要一个给定的核与图像进行“卷积”(convolve),但是NumPy碰巧只接受一维数组。但是并不是说不能用NumPy完成多维数组的卷积运算,只是有些复杂。而ndimage(它是SciPy的

  一部分)的convolve()函数可以解决这个问题,该函数支持经典的NumPy数组,cv2模块用这种数组来存储图像。

  上面的代码用了两个自定义的卷积核来实现两个高通滤波器。最后会用一周不同的方法来实现一个高通滤波器:通过对象图像应用低通滤波器之后,与原始图像计算差值。第三种方法得到的效果最好。

  2.2、低通滤波器

    高通滤波器是根据像素与周围像素的亮度差值来提示该像素的亮度,低通滤波器(Low Pass Filter,LPF)则是在像素与周围像素的亮度差值小于一个特定值时,平滑该像素的亮度。

  它主要用于去噪和模糊化,比如数,高斯模糊是最常用的模糊滤波器(平滑滤波器)之一,它是一个削弱高频信号强度的低通滤波器。

  3、边缘检测

    边缘在人类视觉和计算机视觉中均起着重要的的作用。人类能够凭借一张背景剪影或一个草图就识别出物体的类型和姿态。事实上,艺术强调边缘和姿态,

  它们通常传达了原型(archetype)的思想,比如Rodin的《思考者》和Joe Shuster的《超人》。软件也一样,它可以推理出边缘、姿态以及原型。

    OpenCV提供了许多边缘检测滤波函数,包括Laplacian()、Sobel()以及Scharr()。这些滤波函数都会将边缘区域转为黑色,将边缘区域转为白色或其它饱和的颜色。但是,

  这些函数很容易将噪声错误地识别为边缘。缓解这个问题的办法是在找到边缘之前对图像进行模糊处理。OpenCV也提供了许多模糊滤波函数,包括blur()(简单是算术平均),medianBlur()以及

  GaussianBlur()。边缘检测函数和模糊滤波函数有很多参数,但总会有一个ksize参数,它是一个奇数,表示高滤波的宽和高(以像素为单位)。

    这里使用medianBlur()作为模糊函数,它对去除数字化的视频噪声非常有效,特别是去除彩色图像的噪声;使用Laplacian()作为边缘检测函数,它会产生明显的边缘线条,

  灰度图像更是如此。在使用medianBlur()函数之后,将要使用Laplacian()函数之前,需要将图像从BGR色彩空间灰度色彩空间。

    在得到Laplacian()函数的结果之后,需要将其转换成黑色边缘和黑色背景的图像。然后将其归一化(使它的像素值在0到1之间),并乘以源图像以便将边缘变黑。

    代码实现如下:

def strokeEdges(src,dst,blurKsize = 7,edgeKsize = 5):
if blurKsize >= 3:
blurredSrc = cv2.medianBlur(src,blurKsize)
graySrc = cv2.cvtColor(blurredSrc, cv2.COLOR_BGR2GRAY)
else:
graySrc = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
cv2.Laplacian(graySrc,cv2.CV_8U,graySrc,ksize=edgeKsize)
normalizedInverseAlpha = (1.0/255)*(255-graySrc)
channels = cv2.split(src)
for channel in channels:
channel[:] = channel * normalizedInverseAlpha
cv2.merge(channels,dst)

    注意,核的大小可由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)

  锐化、边缘检测以及模糊等滤波器都是用了高度对称的核。但是有时不对称的核也会得到一些有趣的效果。

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 for python3 学习笔记3-----用OpenCV3处理图像一的更多相关文章

  1. OpenCV3 for python3 学习笔记3-----用OpenCV3处理图像2

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

  2. OpenCV3 for python3 学习笔记1

    1.读/写图像文件 OpenCV的imread()函数和imwrite()函数能支持各种静态图像文件格式.不同系统支持的文件格式不一样,但都支持BMP格式,通常还应该支持PNG.JPEG和TIFF格式 ...

  3. OpenCV3 for python3 学习笔记2

    1.安装 如果你是第一次使用OpenCV Python开发包,想要安装OpenCV Python只要执行如下命令行即可:  pip install opencv-python   如果你还想使用Ope ...

  4. Python3学习笔记(urllib模块的使用)转http://www.cnblogs.com/Lands-ljk/p/5447127.html

    Python3学习笔记(urllib模块的使用)   1.基本方法 urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None,  ...

  5. Python3学习笔记 - 准备环境

    前言 最近乘着项目不忙想赶一波时髦学习一下Python3.由于正好学习了Docker,并深深迷上了Docker,所以必须趁热打铁的用它来创建我们的Python3的开发测试环境.Python3的中文教程 ...

  6. python3学习笔记(7)_listComprehensions-列表生成式

    #python3 学习笔记17/07/11 # !/usr/bin/env python3 # -*- conding:utf-8 -*- #通过列表生成式可以生成格式各样的list,这种list 一 ...

  7. python3学习笔记(6)_iteration

    #python3 学习笔记17/07/10 # !/usr/bin/env python3 # -*- coding:utf-8 -*- #类似 其他语言的for循环,但是比for抽象程度更高 # f ...

  8. python3学习笔记(5)_slice

    #python3 学习笔记17/07/10 # !/usr/bin/env python3 # -*- coding:utf-8 -*- #切片slice 大大简化 对于指定索引的操作 fruits ...

  9. Python3学习笔记01-环境安装和运行环境

    最近在学习Python3,想写一些自己的学习笔记.方便自己以后看,主要学习的资料来自菜鸟教程的Python3教程和廖雪峰官方网站的Python教程. 1.下载 1)打开https://www.pyth ...

随机推荐

  1. 移动端line-height问题

    ios5  上:82px;下:84px; ios6  上:82px;下:84px; ios6 plus 上:124px;下:126px; mi4w 上:118px;下:130px; vivo  上:5 ...

  2. 047 SparkSQL自定义UDF函数

    一:程序部分 1.需求 Double数据类型格式化,可以给定小数点位数 2.程序 package com.scala.it import org.apache.spark.{SparkConf, Sp ...

  3. Spring(二)IOC底层实现原理

    IOC原理 将对象创建交给Spring去管理. 实现IOC的两种方式 IOC配置文件的方式 IOC注解的方式 IOC底层实现原理 底层实现使用的技术 1.1 xml配置文件 1.2 dom4j解析xm ...

  4. Python编程基础(一)

    1.Python中的变量赋值不需要类型声明 2.等号(=)用来给变量赋值 3.字符串拼接用  “+”  号 temp=‘123’ print('temp的值是%s'%temp) #整数和字符创的转换, ...

  5. POJ 3169 Layout 【差分约束】+【spfa】

    <题目链接> 题目大意: 一些母牛按序号排成一条直线.有两种要求,A和B距离不得超过X,还有一种是C和D距离不得少于Y,问可能的最大距离.如果没有最大距离输出-1,如果1.n之间距离任意就 ...

  6. 我与Vuex的第一次邂逅

    new Vue({ // state data () { return { count: 0 } }, // view template: ` <div>{{ count }}</d ...

  7. javaScript函数节流与函数防抖

    javaScript函数节流与防抖之区别 函数防抖(debounce)与函数节流(throttle)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟.假死或卡顿 ...

  8. Alpha(1/10)

    鐵鍋燉腯鱻 项目:小鱼记账 团队成员 项目燃尽图 冲刺情况描述 站立式会议照片 各成员情况 团队成员 学号 姓名 git地址 博客地址 031602240 许郁杨 (组长) https://githu ...

  9. java反射机制基础

    java反射机制: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和 属性:这种动态获取信息以及动态调用对象方法的功能称为j ...

  10. VS2013 C#中调用DLL

    winform界面中,使用C#编程调用DLL过程记录: (1)什么是DLL 动态链接库英文为DLL,是Dynamic Link Library 的缩写形式,DLL 是一个包含可由多个程序同时使用的代码 ...