当前位置 博文首页 > Asia-Lee:图像处理基础操作一
目录
一、图像基础
二、图像基本操作
1、图像数据读取与写入
2、视频数据读取
3、图像颜色通道提取与合并
4、图像边界填充
5、图像融合及类型转换
三、图像的几何变换
1、图像缩放
2、图像旋转
3、图像翻转
4、图像平移
5、图像仿射变换
6、图像透视变换
四、图像阈值化与平滑处理
1、图像阈值化处理
2、图像平滑处理
五、图像形态学操作
1、腐蚀操作
2、膨胀操作
3、开运算
4、闭运算
5、梯度运算
6、顶帽运算
7、黑帽运算
图像处理:对输入的图像做某种变换,输出仍然是图像,基本不涉及或者很少涉及图像内容的分析。比较典型的有图像变换,图像增强,图像去噪,图像压缩,图像恢复,二值图像处理等等。基于阈值的图像分割也属于图像处理的范畴。一般处理的是单幅图像。
图像分析:对图像的内容进行分析,提取有意义的特征,以便于后续的处理。处理的仍然是单幅图像。
计算机视觉:对图像分析得到的特征进行分析,提取场景的语义表示,让计算机具有人眼和人脑的能力。这时处理的是多幅图像或者序列图像,当然也包括部分单幅图像。
图像都是由像素构成的,即图像中的小方格,这些小方格都有一个明确的位置和被分配的色彩数值,这些小方格的颜色和位置就决定该图像所呈现出来的样子。像素是图像中的最小单位,每一个点阵图像包含了一定量的像素,这些像素决定图像在屏幕上所呈现的大小。
图像通常包括二值图像、灰度图像和彩色图像,具体如下:
import cv2 # opencv读取的格式是BGR
import numpy as np
#图像显示
def cv_show(name,img):
cv2.imshow(name,img) # 图像的显示,也可以创建多个窗口
cv2.waitKey(0) # 等待时间,毫秒级,0表示任意键终止
cv2.destroyAllWindows() #删除所有窗口
img=cv2.imread('data/cat.jpg',cv2.IMREAD_COLOR) # 读取彩色图像
cat_new=img[0:100,0:200] #截取部分图像数据
cv_show('cat_new',cat_new) #显示截取后的图像
cv2.imwrite('data/cat_new.png',img) #图像的保存
vc = cv2.VideoCapture('data/test.mp4')
# 检查是否打开正确
if vc.isOpened():
oepn, frame = vc.read()
else:
open = False
while open:
ret, frame = vc.read()
if frame is None:
break
if ret == True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('result', gray)
if cv2.waitKey(100) & 0xFF == 27:
break
vc.release()
cv2.destroyAllWindows()
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img=cv2.imread('data/cat.jpg',cv2.IMREAD_COLOR) # 读取彩色图像
b,g,r=cv2.split(img) # 拆分颜色通道
print(r.shape) # (414, 500)
img=cv2.merge((b,g,r)) # 合并颜色通道
print(img.shape) #(414, 500, 3)
# 只保留R
r_img = img.copy()
r_img[:,:,0] = 0
r_img[:,:,1] = 0
cv_show('R',cur_img)
结果为:
注意:OpenCV读取的彩色图像由B、G、R三原色组成,也可以通过下面代码获取不同的通道,b = img[:, :, 0],g = img[:, :, 1],r = img[:, :, 2];opencv和matplotlib读取RGB通道的顺序是不一样的,opencv的顺序是B-G-R,而matplotlib的顺序是R-G-B,下面使用matplotlib读取并显示图片
import cv2 # opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread('data/cat.jpg',cv2.IMREAD_COLOR) # 读取彩色图像
b,g,r=cv2.split(img) # 拆分颜色通道
img=cv2.merge((b,g,r)) # 合并颜色通道
# 只保留B
b_img = img.copy()
b_img[:,:,0] = 0
b_img[:,:,1] = 0
plt.subplot(131)
plt.imshow(b_img)
plt.title('Blue')
# 只保留G
g_img = img.copy()
g_img[:,:,0] = 0
g_img[:,:,2] = 0
plt.subplot(132)
plt.imshow(g_img)
plt.title('Green')
# 只保留B
r_img = img.copy()
r_img[:,:,1] = 0
r_img[:,:,2] = 0
plt.subplot(133)
plt.imshow(r_img)
plt.title('Red')
结果为:
import cv2 # opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np
top_size,bottom_size,left_size,right_size = (50,50,50,50)
replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)
plt.subplot(231), plt.imshow(img, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')
plt.show()
结果为:
img
:需要填充的图像;top
:图像上边界需要填充的像素点;bottom
:图像下边界需要填充的像素点;left
:图像左边界需要填充的像素点;right
:图像右边界需要填充的像素点;borderType
:图像填充的方法。填充方法主要包括:BORDER_REPLICATE
:复制法,也就是复制最边缘像素,BORDER_REFLECT
:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb,BORDER_REFLECT_101
:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba,BORDER_WRAP
:外包装法abcdefgh|abcdefgh|abcdefg,BORDER_CONSTANT
:常量法,常数值填充,需要在设置一个value值,已显示填充的颜色。图像融合通常是指将2张或2张以上的图像信息融合到1张图像上,融合的图像含有更多的信息,能够更方便人们观察或计算机处理。通过图像融合可以将两张不清晰的图像融合得到更清晰的图。图像融合是在图像加法的基础上增加了系数和亮度调节量。
import cv2 # opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np
img_cat=cv2.imread('data/cat.jpg')
img_dog=cv2.imread('data/dog.jpg')
print(img_cat.shape) #(414, 500, 3)
print(img_dog.shape) #(429, 499, 3)
img_dog = cv2.resize(img_dog, (500, 414))
print(img_dog.shape) #(414, 500, 3)
res = cv2.resize(img, (0, 0), fx=3, fy=1)
plt.imshow(res)
img_cat1 = img_cat+10 #对三个通道像素点进行加10操作
plt.imshow(img_cat1)
img_new=img_cat+img_dog #将两张图片进行相加操作, 如果大于255,就使用256进行约分
plt.imshow(img_new)
img_add=cv2.add(img_cat, img_dog) #使用cv2.add对两个照片进行加和, 如果加和值大于255,就使用255表示
plt.imshow(img_add)
res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0) #将两个图片进行重叠
plt.imshow(res)
图像类型转换:图像类型转换是指将一种类型转换为另一种类型,比如彩色图像转换为灰度图像、BGR图像转换为RGB图像。OpenCV提供了200多种不同类型之间的转换,其中最常用的如下:
img=cv2.imread('data/cat.jpg')
rows,cols=img.shape[:2]
img_new = cv2.resize(img, (int(cols*0.6), int(rows*1.2)))
plt.imshow(img_new)
import cv2
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread('data/cat.jpg')
rows,cols,channel=img.shape
M=cv2.getRotationMatrix2D((cols/2,rows/2),30,1) #绕图像的中心旋转,参数:旋转中心 旋转度数 scale
img_new=cv2.warpAffine(img,M,(cols,rows)) #参数:原始图像 旋转参数 变换后图像的宽高
plt.imshow(img_new)
图像翻转在OpenCV中调用函数flip()实现,cv2.flip(img, flipCode):其中img表示原始图像,flipCode表示翻转方向,如果flipCode为0,则以X轴为对称轴翻转,如果fliipCode>0则以Y轴为对称轴翻转,如果flipCode<0则在X轴、Y轴方向同时翻转。
import cv2
import matplotlib.pyplot as plt
img=cv2.imread('img/cat.jpg')
src=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
img1=cv2.flip(src,0) #以X轴为对称轴翻转
img2=cv2.flip(src,1) #以Y轴为对称轴翻转
img3=cv2.flip(src,-1) #X轴Y轴方向同时翻转
#显示图形
titles = ['Source', 'Image1', 'Image2', 'Image3']
images = [src, img1, img2, img3]
for i in range(4):
plt.subplot(2,2,i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
图像平移首先定义平移矩阵M,再调用warpAffine()函数实现平移,核心函数如下:M = np.float32([[1, 0, x], [0, 1, y]]),
?cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图片
img = cv2.imread('img/cat.jpg')
image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 图像向下平移
M = np.float32([[1, 0, 0], [0, 1, 100]])
img1 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
#图像向上平移
M = np.float32([[1, 0, 0], [0, 1, -100]])
img2 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
#图像向右平移
M = np.float32([[1, 0, 100], [0, 1, 0]])
img3 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
#图像向左平移
M = np.float32([[1, 0, -100], [0, 1, 0]])
img4 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
# 显示图形
titles = ['Image1', 'Image2', 'Image3', 'Image4']
images = [img1, img2, img3, img4]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
src = cv2.imread('img/cat.jpg')
#获取图像大小
rows, cols = src.shape[:2]
#设置图像仿射变换矩阵
pos1 = np.float32([[50,50], [200,50], [50,200]])
pos2 = np.float32([[10,100], [200,50], [100,250]])
M = cv2.getAffineTransform(pos1, pos2)
#图像仿射变换
img_new = cv2.warpAffine(src, M, (cols, rows))
#显示图像
images=[src,img_new]
for i in range(2):
plt.subplot(1,2,i+1)
plt.imshow(images[i])
plt.show()
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
src = cv2.imread('img/cat.jpg')
#获取图像大小
rows, cols = src.shape[:2]
#设置图像透视变换矩阵
pos1 = np.float32([[114, 82], [287, 156], [8, 322], [216, 333]])
pos2 = np.float32([[0, 0], [188, 0], [0, 262], [188, 262]])
M = cv2.getPerspectiveTransform(pos1, pos2)
#图像透视变换
img_new= cv2.warpPerspective(src, M, (190, 272))
#显示图像
images=[src,img_new]
for i in range(2):
plt.subplot(1,2,i+1)
plt.imshow(images[i])
plt.show()
图像的二值化或阈值化(Binarization)旨在提取图像中的目标物体,将背景以及噪声区分开来。通常会设定一个阈值T,通过T将图像的像素划分为两类:大于T的像素群和小于T的像素群。
灰度转换处理后的图像中,每个像素都只有一个灰度值,其大小表示明暗程度。二值化处理可以将图像中的像素划分为两类颜色,当灰度Gray小于阈值T时,其像素设置为0,表示黑色;当灰度Gray大于或等于阈值T时,其Y值为255,表示白色。
二值化处理广泛应用于各行各业,比如生物学中的细胞图分割、交通领域的车牌设别等。在文化应用领域中,通过二值化处理将所需民族文物图像转换为黑白两色图,从而为后面的图像识别提供更好的支撑作用。
OpenCV中提供了阈值函数threshold()实现二值化处理:retval, dst = cv2.threshold(src, thresh, maxval, type)
二值化操作的类型主要包含以下5种类型:
import cv2
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread('data/cat.jpg')
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
cv2.threshold()函数中的参数img_gray表示灰度图,参数127表示对像素值进行分类的阈值,参数255表示像素值高于阈值时应该被赋予的新像素值,最后一个参数对应不同的阈值处理方法。结果如下图:
图像增强:图像增强是对图像进行处理,使其比原始图像更适合于特定的应用,它需要与实际应用相结合。对于图像的某些特征如边缘、轮廓、对比度等,图像增强是进行强调或锐化,以便于显示、观察或进一步分析与处理。图像增强的方法是因应用不同而不同,研究内容包括:
图像平滑:图像平滑是一种区域增强的算法,平滑算法有邻域平均法、中值滤波、边界保持类滤波等。在图像产生、传输和复制过程中,常常会因为多方面原因而被噪声干扰或出现数据丢失,降低了图像的质量(某一像素,如果它与周围像素点相比有明显的不同,则该点被噪声所感染)。这就需要对图像进行一定的增强处理以减小这些缺陷带来的影响。
邻域平均法:图像简单平滑是指通过邻域简单平均对图像进行平滑处理的方法,用这种方法在一定程度上消除原始图像中的噪声、降低原始图像对比度的作用。它利用卷积运算对图像邻域的像素灰度进行平均,从而达到减小图像中噪声影响、降低图像对比度的目的。邻域平均法主要缺点是在降低噪声的同时使图像变得模糊,特别在边缘和细节处,而且邻域越大,在去噪能力增强的同时模糊程度越严重。
滤波器:在图像简单平滑中,算法利用卷积模板逐一处理图像中每个像素,这一过程可以形象地比作对原始图像的像素一一进行过滤整理,在图像处理中把邻域像素逐一处理的算法过程称为滤波器。平滑线性滤波器的工作原理是利用模板对邻域内像素灰度进行加权平均,也称为均值滤波器
为图像增加噪声如下
# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("img/cat.jpg", cv2.IMREAD_UNCHANGED)
rows, cols, chn = img.shape
# 为图片增加噪声
for i in range(5000):
x = np.random.randint(0, rows)
y = np.random.randint(0, cols)
img[x, y, :] = 255
plt.imshow(img)
plt.show()
(1)均值滤波
均值滤波是指任意一点的像素值,都是周围N*M个像素值的均值。Python调用OpenCV实现均值滤波的核心函数如下:
result = cv2.blur(原始图像,核大小)其中,核大小是以(宽度,高度)表示的元祖形式。常见的形式包括:核大小(3,3)和(5,5)。核如果设置为(1,1)处理结果就是原图,核中每个权重值相同,称为均值。核越大图像会变的越模糊。
# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("img/cat.jpg", cv2.IMREAD_UNCHANGED)
rows, cols, chn = img.shape
# 为图片增加噪声
for i in range(5000):
x = np.random.randint(0, rows)
y = np.random.randint(0, cols)
img[x, y, :] = 255
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 均值滤波
result = cv2.blur(source, (5, 5))
# 显示图形
titles = ['Source Image', 'Blur Image']
images = [source, result]
for i in range(2):
plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
(2)方框滤波
方框滤波和均值滤波核基本一致,区别是需不需要均一化处理。OpenCV调用boxFilter()函数实现方框滤波。函数如下:
result = cv2.boxFilter(原始图像, 目标图像深度, 核大小, normalize属性),其中,目标图像深度是int类型,通常用“-1”表示与原始图像一致;核大小主要包括(3,3)和(5,5)normalize属性表示是否对目标图像进行归一化处理。当normalize为true时需要执行均值化处理,当normalize为false时,不进行均值化处理,实际上为求周围各像素的和,很容易发生溢出,溢出时均为白色,对应像素值为255。