数字图像处理的本质就是操作矩阵,在Python中图像对应的Numpy的ndarray。所以做图像处理会使用numpy会很方便的。
1.图像的读、写、显示
cv2.imread("图像路径名",读取方式)
读取方式有:
IMREAD_ANYCOLOR = 4
IMREAD_ANYDEPTH = 2
IMREAD_COLOR = 1
IMREAD_GRAYSCALE = 0
IMREAD_LOAD_GDAL = 8
IMREAD_UNCHANGED = -1
通常读取方式可以不写,默认是以BGR彩色图片读取的;或者读取方式写0,表示以灰度图的方式读取。
其他简单的函数代码中解释:
import cv2 as cv
img = cv.imread("./images/xiao.jpg")
cv.namedWindow("xiao") # 创建名字为xiao的窗口(不创建也可以)
cv.imwrite("jiang.jpg", img) # 将img存到本地,名字为jiang.jpg
cv.imshow("xiao", img) # 在xiao窗口中显示图片img
cv.waitKey() # 等待按键ESC退出窗口
cv.destoryAllWindows() # 释放由OpenCV创建的所有窗口
其中imwrite()也可以保存为图像的其他格式(jpg, png),也可以选择保存的图片质量
cv.imwrite("jiang1.jpg", img, [int(cv.IMWRITE_JPEG_QUALITY), 5])
cv.imwrite("jiang2.jpg", img, [int(cv.IMWRITE_JPEG_QUALITY), 100])
# 对于JPEG,其表示的是图像的质量,用0-100的整数表示,默认为95。
# 注意,cv2.IMWRITE_JPEG_QUALITY类型为Long,必须转换成int。
cv.imwrite("jiang3.png", img, [int(cv.IMWRITE_PNG_COMPRESSION), 0])
cv.imwrite("jiang4.png", img, [int(cv.IMWRITE_PNG_COMPRESSION), 9])
# 对于PNG,第三个参数表示的是压缩级别。cv2.IMWRITE_PNG_COMPRESSION,
# 从0到9,压缩级别越高,图像尺寸越小。默认级别为3.
2.图像的加、混合、位运算
cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])
此函数可以用表达式计算:
dst = src1 * alpha + src2 * beta + gamma
dtype为输出图像的深度,当两个图像是相同的话为-1(一般不作设置)
此函数中的两幅图像必须是尺寸相同、类型相同的。alpha+beta=1,分别取不同的值有不同的效果。
图像的位操作:图像与运算cv2.bitwise_and,图像或运算cv2.bitwise_or,图像非运算cv2.bitwise_not与图像异或运算cv2.bitwise_xor。
1)图像与运算-cv2.bitwise_and(src1, src2, dst=None, mask = None)
2)图像或运算-cv2.bitwise_or(src1, src2, dst=None, mask = None)
3)图像非运算-cv2.bitwise_not(src1, src2, dst=None, mask = None)
图像非运算的效果:一个二值图,将黑色转为白色,白色转为黑色。
4) 图像异或运算-cv2.bitwise_xor(src1, src2, dst=None, mask = None)
这四个运算,最少要有两个参数,即src1,src2;dst:参数返回结果可选;mask:参数也是可选的,指定mask区域进行操作。
import numpy as np
import cv2 as cv
img1 = cv.imread("./images/xiao.jpg")
img2 = cv.imread("./images/er.jpg")
mask = np.zeros((200, 200), np.uint8) # 创建一个掩膜(全黑)
mask[50:150, 50:150] = 255 # 将掩膜中间部分变为白的
mask_inv = cv.bitwise_not(mask) # 反转颜色
res = cv.add(img1, img1) # 图像加法 将img1与img1相加
dst = cv.addWeighted(img1, 0.5, img2, 0.5, 0) # 根据权重将两张图片相加
# 与掩码mask进行位运算,只显示中间部分
img_mask = cv.bitwise_and(img1, img1, mask=mask)
# 与掩码mask_inv进行位运算,只显示除中间以外部分
img_mask_inv = cv.bitwise_and(img2, img2, mask=mask_inv)
cv.imshow("img1", img1)
cv.imshow("img2", img2)
cv.imshow("res", res)
cv.imshow("dst", dst)
cv.imshow("mask1", img_mask)
cv.imshow("mask2", img_mask_inv)
cv.waitKey()
cv.destoryAllWindows()
下图为运行结果:
3.图像通道的拆分与合并
读入BGR图像之后,可以对图像的各个通道进行拆分(cv2.split)分别得到三个通道,也可以对三个通道进行合并得到BGR图像。下面使用OpenCV的函数以及Numpy操作对图像实现拆分与合并,图像的0,1,2通道分别对应B,G,R三个通道
import cv2 as cv
import numpy as np
img = cv.imread("./images/er.jpg")
# 使用numpy进行分割
# b = np.zeros((img.shape[0], img.shape[1]), dtype=img.dtype)
# g = np.zeros((img.shape[0], img.shape[1]), dtype=img.dtype)
# r = np.zeros((img.shape[0], img.shape[1]), dtype=img.dtype)
# b[:, :] = img[:, :, 0] # B蓝色通道
# g[:, :] = img[:, :, 1] # G绿色通道
# r[:, :] = img[:, :, 2] # R红色通道
# 使用OpenCV进行分割
b, g, r = cv.split(img)
# 使用OpenCV进行合并
merged = cv.merge([b, g, r])
print("Merge by OpenCV")
print(merged.strides)
print(merged)
# 使用Numpy进行合并
mergedByNp = np.dstack([b, g, r])
print("Merge by NumPy ")
print(mergedByNp.strides)
print(mergedByNp)
cv.imshow("Merged", merged)
cv.imshow("MergedByNp", mergedByNp)
cv.imshow("Blue", b)
cv.imshow("Red", r)
cv.imshow("Green", g)
cv.waitKey(0)
cv.destroyAllWindows()
可能红绿蓝通道和自己想的不一样,为了转换为我所想的,所以这里需要把b,g,r所对应的单通道转换为三通道的,其余两个通道使用0填充即可,添加以下代码,实现了自己原本想象的红绿蓝通道的图像:
zeros = np.zeros(img.shape[:2], np.uint8)
b = cv.merge([b, zeros, zeros])
g = cv.merge([zeros, g, zeros])
r = cv.merge([zeros, zeros, r])
图像的基本操作还有很多,基于Numpy可以改变某个像素的值或者多个像素的值,这里就不做介绍了(懂点Numpy的应该都会做吧),主要是要对数字图像和Numpy的ndarray有些了解,今天先到这里吧。
图像的处理还是很好玩的,继续坚持,每天学一点,加油!