005

opencv:图像处理和计算机视觉,C++库的Python接口

人的视觉是三维转二维,计算机视觉要进一步发展就得跳脱到三维空间

基本任务

语义分割

Semantic Segmentation

目标定位与识别

Classification and Localization

目标检测

Object Detection

Region Proposal:目标候选区域

select

sudo pip install opencv -python

1
2
3
4
import cv2 as cv
img=cv.imread('aa.png')
img.shape
type(img)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np
# 灰度图
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
cv.imwrite('img/Lenna_gray.png', img_gray)
# 二值化
_, img_bin = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY)
cv.imwrite('img/Lenna_bin.png', img_bin)
# 平滑
img_blur = cv.blur(img, (5, 5))
cv.imwrite('img/Lenna_blur.png', img_blur)
# 边缘提取
_, contours, _ = cv.findContours(img_bin, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
img_cont = np.zeros(img_bin.shape, np.uint8)
cv.drawContours(img_cont, contours, -1, 255, 3)
cv.imwrite('img/Lenna_cont.png', img_cont)

Pillow

pillow:基础的数字图像处理,操作图像的功能强大,API简单易用。

  • PIL(Python Imaging Library)仅支持到Python 2.7,加上年久失修,所以诞生了Pillow

基本操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from PIL import Image


im = Image.open('test.jpg')


# 获得图像尺寸:
w, h = img.size
img.width
img.height
img.format
# 保存
img.sage('aa.bmp')
im.save('bb.jpg','jpeg') #thumbnail无返回值

像素操作

1
2
3
4
5
6
im.getpixel((100,80))  #元组坐标取像素
im.putpixel((100,80),(128,30,120)) #修改像素


m.histogram() #如果图像包含多个通道,则返回所有通道的直方图
im.histogram()[:256] #查看第一个通道的直方图

高级操作

缩放

1
2
3
4
5
6

# 缩放到50%:
im.resize((w//2,h//2)).save('aa.jpg','jpeg')
im=im.resize((100,100)) #缩放到新的像素大小
# 另有一个thumbnail(),封装了resize,没有返回值,按比例缩小
im.thumbnail((w//2,h//2))

旋转

1
2
3
4
5
6
# ratate:任意角度旋转
im=im.ratato(90) #逆时针90度
# transpose:特殊角度的旋转加翻转
im=im.transpose(img.ROTATE_180)
im=im.transpose(Image.FLIP_LEFT_RIGHT)
im=im.transpose(Image.FLIP_TOP_BOTTOM)

裁剪

1
2
3
4
box=(120,194,220,294)
region=im.crop(box)
region=region.transpose(Image.ROTATE_180)
im.paste(region,box)

图像通道分离与合并

r, g, b = im.split() #将彩色图像分离为同样大小的红、绿、蓝三分量子图
imNew = Image.merge(im.mode, (r,g,b))
(12)创建缩略图
im.thumbnail((50, 20)) #参数为缩略图尺寸
im.save(‘2.jpg’) #保存缩略图
(13)屏幕截图
from PIL import ImageGrab
im = ImageGrab.grab((0,0,800,200)) #截取屏幕指定区域的图像
im = ImageGrab.grab() #不带参数表示全屏幕截图
(14)图像增强
from PIL import ImageFilter
im = im.filter(ImageFilter.DETAIL) #创建滤波器,使用不同的卷积核
im = im.filter(ImageFilter.EDGE_ENHANCE) #边缘增强
im = im.filter(ImageFilter.EDGE_ENHANCE_MORE) #边缘增强
(15)图像模糊
im = im.filter(ImageFilter.BLUR)
im = im.filter(ImageFilter.GaussianBlur) #高斯模糊
im.filter(ImageFilter.MedianFilter) #中值滤波
(16)图像边缘提取
im = im.filter(ImageFilter.FIND_EDGES)
(17)图像点运算
im = im.point(lambda i:i1.3) #整体变亮
im = im.point(lambda i:i
0.7) #整体变暗
im = im.point(lambda i: i1.8 if i<100 else i0.7) #自定义调整图像明暗度
也使用图像增强模块来实现上面类似的功能,例如
from PIL import ImageEnhance
enh = ImageEnhance.Brightness(im)
enh.enhance(1.3).show()
(18)图像冷暖色调整
r, g, b = im.split() #分离图像
r = r.point(lambda i:i1.3) #红色分量变为原来的1.3倍
g = g.point(lambda i:i
0.9) #绿色分量变为原来的0.9
b = b.point(lambda i:0) #把蓝色分量变为0
im = Image.merge(im.mode,(r,g,b)) #合并图像
im.show()
(19)图像对比度增强
from PIL import ImageEnhance
im = ImageEnhance.Contrast(im)
im = im.enhance(1.3) #对比度增强为原来的1.3倍

其他功能如切片、旋转、滤镜、输出文字、调色板等一应俱全。

比如,模糊效果也只需几行代码:

1
2
3
4
5
6
7
from PIL import Image, ImageFilter

# 打开一个jpg图像文档,注意是当前路径:
im = Image.open('test.jpg')
# 应用模糊滤镜:
im2 = im.filter(ImageFilter.BLUR)
im2.save('blur.jpg', 'jpeg')

PIL的ImageDraw提供了一系列绘图方法,让我们可以直接绘图。比如要生成字母验证码图片:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
from PIL import Image, ImageDraw, ImageFont, ImageFilter

import random

# 随机字母:
def rndChar():
return chr(random.randint(65, 90))

# 随机颜色1:
def rndColor():
return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255))

# 随机颜色2:
def rndColor2():
return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127))

# 240 x 60:
width = 60 * 4
height = 60
image = Image.new('RGB', (width, height), (255, 255, 255))
# 创建Font对象:
font = ImageFont.truetype('Arial.ttf', 36)
# 创建Draw对象:
draw = ImageDraw.Draw(image)
# 填充每个像素:
for x in range(width):
for y in range(height):
draw.point((x, y), fill=rndColor())
# 输出文字:
for t in range(4):
draw.text((60 * t + 10, 10), rndChar(), font=font, fill=rndColor2())
# 模糊:
image = image.filter(ImageFilter.BLUR)
image.save('code.jpg', 'jpeg')

我们用随机颜色填充背景,再画上文字,最后对图像进行模糊,得到验证码图片如下:

如果运行的时候报错:

1
IOError: cannot open resource

这是因为PIL无法定位到字体文档的位置,可以根据操作系统提供绝对路径,比如:

1
'/Library/Fonts/Arial.ttf'
  • convert(): 顾名思义, 转换图片格式用的, 我们最好能将图片的格式转换成jpg, 符合网络图片的传输标准. 此外, 还发现了一个有趣的公式, L = R * 299/1000 + G * 587/1000 + B * 114/1000, 将彩色图片转换为黑白图片. greyscale(‘L’), color(‘RGB’)
  • crop(): 返回图片的一个方形区域, 参数box为包含四个整型的tuple, 格式为(left, upper, right, lower)
  • filter(): 给图片上滤镜效果, 滤镜几个效果在ImageFilter.py文档中可以查到, 主要有BLUR, CONTOUR, DETAL, SMOOTH, SHARPEN, EMBOSS, ENHANCE等
  • getbands(): 又是一个有意思的函数, 返回当前图片的已有通道.(RGB)
  • getcolor(): 返回一个列表, 列表包含图片中所有的用到的颜色, maxcolors参数用于设定返回颜色个数的最大值, 如果图片有的颜色超过这个值, 那么就返回None; 这个函数的有趣之处在于, 返回的列表有如下的形式: [Num,(#R, #G, #B), …], 也就是说可以统计图片中颜色出现的像素个数;
  • getdata(): 以一个sequence-like形式返回当前图片所有像素点的颜色值.
  • getextrema(): 这也是一个有意思的函数, 得到返回三个通道(RGB)中的最大和最小值.
  • getpixel(): 返回tuple指定位置的颜色值
  • paste(): 将另外一副图片黏贴当前图片, 可以用来打水印
  • put*(): 各种put函数, 用于修改当前图片的一些参数
  • resize(): 修改图片的size, resample参数传入采样算法, 一般使用高质量缩放的Image.LANCZOS参数
  • rotate(): 旋转图片, 参数angle表示旋转的逆时针方向角度
  • save(): 保存Image对象, 输入保存格式和保存文档名. 一般的用法为img.save("test.jpg", format="jpeg")
  • show(): 查看当前图片, 不同系统用不同的处理方法, Windows和Mac OS X中, 会将图片保存为一个临时BMP文档
  • split(): 将原图分裂到三个通道, 返回一个三元tuple, 每个tuple为一个仅仅含有某个通道的Image对象
  • thumbnail(): 制作当前图片的缩略图, 参数size指定了图片的最大的宽度和高度
  • transform(): 对图片进行一些奇奇怪怪的处理. 为什么用奇奇怪怪来形容? 因为我不知道参数data是干嘛的…(该参数在Image.__transformer()中提到)
  • transpose(): 就是PIL中预置的翻转函数, 参数method的值可以为Image.FLIP_LEFT_RIGHT, Image.FLIP_TOP_BOTTOM, Image.ROTATE_90, Image.ROTATE_180, Image.ROTATE_270, Image.TRANSPOSE. 基本上常用的方法就是上面这些了, 根据我们的需求, 我们要使用的方法也就是thumbnail(), 或者resize()

Image.resize()和Image.thumbnail()的区别

根据代码和代码注释, 这两个函数都是对图片进行缩放, 两者的主要区别如下:

  1. resize()函数会返回一个Image对象, thumbnail()函数返回None
  2. resize()修改后的图片在返回的Image中, 而原图片没有被修改; thumbnail()直接对内存中的原图进行了修改, 但是修改需要保存
  3. resize()中的size参数直接设定了resize之后图片的规格, 而thumbnail()中的size参数则是设定了x/y上的最大值. 也就是说, 经过resize()处理的图片可能会被拉伸, 而经过thumbnail()处理的图片不会被拉伸
  4. thumbnail()函数内部调用了resize(), 可以认为thumbnail()是对resize()的一种封装

两个函数的基本调用方式如下:

1
2
3
4
5
6
7
8
9
from PIL import Image
# Image.resize usage
with Image.open("test.jpg") as img:
resized = img.resize((new_x, new_y), resample=Image.LANCZOS)
resized.save("resized.jpg", format="jpeg")
# Image.thumbnail usage
with Image.open("test.jpg") as img:
img.thumbnail((max_x, max_y), resample=Image.LANCZOS)
img.save("thumbnail.jpg", format="jpeg")

scikit-image

它使图像处理任务如模糊,增强对比度,缩放只需要一些函数调用就可以完成。

概述

前置包

numpy+matplotlib+scipy+scikit-image

io读取/保存/显示图片与视频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from skimage import io
img_path=""
# 读取
img = io.imread('img_path',as_grey=True)
io.imshow(img)
io.show()

# 保存
io.imsave(fname,arr_img)

# 图片信息
type(img)
img.shape 宽,高,通道数
img.size
img.max() 最大像素值
img.min() 最小像素值
img.mean() 像素平均值

color颜色空间变换

data提供一些测试图片和样本数据

1
2
3
4
5
6
7
8
9
10
from skimage import io,data
img=data.log() #商标图像
img2=data.horse() #马的图像
img3=data.clock() #时钟图像
io.imshow(img)
io.show()

# 图像所在地址
from skimage import data_dir
print (data_dir)

filters 图像增强,边缘检测,排序滤波器,自动阈值等
draw 操作于numpy数组上的基本图形绘制,包括线条,矩阵,圆和文本等
transform 几何变换和其他变换,如旋转,拉伸和Radon(拉东)变换等
exposure 图像强度调整,例如,直方图均衡化等
feature 特征检测和提取, 例如,纹理分析等
graph 图论操作,例如,最短路径
measure 图像属性测量,例如,相似度和轮廓
morphology 形态学操作,如开闭运算,骨架提取等
novice 简化的用于教学目的的接口
restoration 修复算法,例如去卷积算法,去噪等
segmentation 图像分割为多个区域
util 通用工具
viewer 简单图形用户接口用于可视