图像处理基础
通勤时间在微信读书上阅读《OpenCV轻松入门:面向Python》的一些笔记,还请各位大佬多多指正
摘要:
- 图像的基本表示方法
- 像素的访问
- 感兴趣区域
- 通道操作
- 图像属性
1 图像的基本表示方法
图片在OpenCV中是用矩阵表示的,二值图和灰度图是一个二维矩阵,矩阵中一个点表示一个像素点;RGB图像是一个三维矩阵,一个向量[r, g, b]表示一个像素点。
1.1 二值图
二值图即黑白图片,二值指的是0和1,其中1表示白,0表示黑。0和1用1位数据就可以表示,但是为了与灰度图表示方法一致,所以通常用0表示黑,255表示白。
import cv2
import numpy as np
def black_white_pic():
black = np.zeros((300, 300), dtype=np.uint8)
white = np.ones((300, 300), dtype=np.uint8) * 255
cv2.imshow("black", black)
cv2.imshow("white", white)
cv2.waitKey()
cv2.destroyAllWindows()
1.2 灰度图
灰度图是只有一个灰色通道的图片,该通道有256个灰度等级,0表示纯黑,255表示白。
def gray_pic():
img = np.random.randint(0, 255, size=(300, 300), dtype=uint8)
print("gray_pic:\n", img)
cv2.imshow("gray_pic", img)
cv2.waitKey()
cv2.destroyAllWindows()
运行结果是不是像极了黑白电视没有信号的亚子
1.3 彩色图片(只介绍RGB)
人眼只有红绿蓝三种颜色感受器,红绿蓝也被称为三基色,其他颜色可由三基色按不同比例组合而成。在彩色图片中存在三个颜色通道,分别为R(红色)通道,G(绿)通道,B(蓝)通道。每个通道都有256个对应通道的颜色等级。在OpenCV中,通道顺序为B-G-R,例如img[5, 10, 0]表示图片img第5行第10列在B通道的像素值。 我们分别设置一个300*300黑色图片的蓝色通道,绿色通道,红色通道有啥效果
def color_pic():
blue = np.ones((300, 300, 3), dtype=np.uint8)
blue[:, :, 0] = 255
cv2.imshow("blue", blue)
green = np.ones((300, 300, 3), dtype=np.uint8)
green[:, :, 1] = 255
cv2.imshow("green", green)
red = np.ones((300, 300, 3), dtype=np.uint8)
red[:, :,2] = 255
cv2.imshow("red", red)
cv2.waitKey(0)
cv2.destroyAllWindows()
2 像素的访问
像素的访问有两种方式: (1)中括号[],彩色图片img[row, col, channel],灰度图img[row, col]。例如,若img为彩色图片,img[0, 3, 1]表示图片img第0行第3列第绿色通道的数据值;im若g为灰度图时,img[0, 3]表示img第0行第3列的数据值; (2)使用内置函数item(),当图片img为彩色图片时,img.item((row, col, channel)),当图片img为灰度图时,调用方式为img.item((row, col, channel))。 特别注意,内置函数Item的效率会由于中括号。
3 感兴趣区域(ROI)
有时候我们会需要操作图片中的某一部分,这部分区域我们称为ROI(Region of Interest),提取感兴趣区域,可以通过中括号[]进行操作
例如,需要把图片行数为200到300,列数为200到300的区域提取出来,可以
roi = img[200:300, 200:300]
接下来我们举一个例子,将图片2的笑脸提取出来并放在图片1中
def ROI_Example():
pic1 = cv2.imread("./myshoot/1.jpg")
pic2 = cv2.imread("./myshoot/2.jpg")
pic1 = cv2.resize(pic1, dsize=(400, 400))
cv2.imshow("pic1", pic1)
cv2.imshow("pic2", pic2)
smile = pic2[70:200, 150:300]
cv2.imshow("smile", smile)
pic1[100:230, 110:260] = smile
cv2.imshow("pic1_smile", pic1)
cv2.waitKey(0)
cv2.destroyAllWindows()
ROI_Example()
运行结果为
4 通道操作
在图像处理过程中,可以对图像的通道进行拆分和合并。
4.1 拆分
拆分有两种方式: 方式一:利用[]进行切片操作; 方式二:调用OpenCV库函数split。 举个例子,将游戏图片每个通道拆分出来,并显示出来,最后再拼接起来。
def Channel_Operation_Example():
img = cv2.imread("./myshoot/game.jpg")
img = cv2.resize(img, dsize=(300, 300))
img_blue = img[:, :, 0]
img_green = img[:, :, 1]
img_red = img[:, :, 2]
i_b = np.zeros(img.shape, dtype=np.uint8)
i_b[:, :, 0] = img_blue
i_g = np.zeros(img.shape, dtype=np.uint8)
i_g[:, :, 1] = img_green
i_r = np.zeros(img.shape, dtype=np.uint8)
i_r[:, :, 2] = img_red
cv2.imshow("i_b", i_b)
cv2.imshow("i_g", i_g)
cv2.imshow("i_r", i_r)
i_blue, i_green, i_red = cv2.split(img)
print("img_blue - i_blue:\n", img_blue - i_blue)
image = np.zeros(img.shape, dtype=np.uint8)
image[:, :, 0] = img_blue
cv2.imshow("b", image)
image[:, :, 1] = img_green
cv2.imshow("b+g", image)
image[:, :, 2] = img_red
cv2.imshow("b+g+r", image)
cv2.waitKey()
cv2.destroyAllWindows()
4.2合并
调用OpenCV库函数cv2.merge([b, g, r])即可
def Channel_Operation_Example2():
img = cv2.imread("./myshoot/game.jpg")
img = cv2.resize(img, dsize=(300, 300))
img_blue = img[:, :, 0]
img_green = img[:, :, 1]
img_red = img[:, :, 2]
game = cv2.merge([img_blue, img_green, img_red])
cv2.imshow("game", game)
cv2.waitKey()
cv2.destroyAllWindows()
5 图像的属性
介绍三种常用的属性
- shape: 彩色图像返回行数,列数,通道数;灰度图像则返回行数和列数
- size:返回行数*列数*通道数的值
- dtype:返回图片数据类型
def get_attribution():
img = cv2.imread('./myshoot/game.jpg')
print("shape: ", img.shape)
print("size: ", img.size)
print("dtype: ", img.dtype)
cv2.destroyAllWindows()
运行结果
总结
- 因为在OpenCV中图片是以矩阵的形式储存,所以图片的部分操作和矩阵操作时一致的。
- 打开图片:image = cv2.imread(path)
- 读取像素值:image[row, col, channel]或者image.item((row, col [, channel]))
- 像素的赋值:image[row, col [, channel]] = val或者image.itemset((row, col [, channel]), val)
- ROI提取:roi = image([row1:row2, col1:col2])
- 通道提取:b, g, r = cv2.split(img)
- 通道合并: img = cv2.merge([b, g, r])
- 图片的属性:shape维度, size数据量, dtype属性
|