2. OpenCV基础知识和绘制图形
###2.1 OpenCV的色彩空间
2.1.1 RGB和BGR
最常见的色彩空间就是RGB, 人眼也是基于RGB的色彩空间去分辨 颜色的.
OpenCV默认使用的是BGR. BGR和RGB色彩空间的区别在于图片在色彩通道上的排列顺序不同.
显示图片的时候需要注意适配图片的色彩空间和显示环境的色彩空间.比如传入的图片是BGR色彩空间, 显示环境是RBG空间, 就会出现颜色混乱的情况.
2.1. 2 HSV, HSL和YUV
2.1.2.1 HSV
- OpenCV用的最多的色彩空间是HSV.
- Hue: 色相, 即色彩, 如红色, 蓝色. 用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°
- Saturation: 饱和度, 表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
- Value: 明度. 明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
为什么要使用HSV?
方便OpenCV做图像处理.比如根据hue的值就可以判断背景颜色.
2.1.2.2 HSL
HSL和HSV差不多.
-
Hue: 色相 -
Saturation: 饱和度 -
Lightness: 亮度
HSL在顶部是纯白的, 不管是什么颜色.
HSV和HSL的区别:
2.1.2.3 YUV
YUV,是一种颜色编码方法。常使用在各个视频处理组件中。 YUV在对照片或视频编码时,考虑到人类的感知能力,允许降低色度的带宽。
“Y”表示明亮度(Luminance或Luma),也就是灰阶值,“U”和“V”表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。
Y’UV的发明是由于彩色电视与黑白电视的过渡时期。
Y’UV最大的优点在于只需占用极少的带宽。
-
4:4:4表示完全取样。 -
4:2:2表示2:1的水平取样,垂直完全采样。 -
4:2:0表示2:1的水平取样,垂直2:1采样。 -
4:1:1表示4:1的水平取样,垂直完全采样。
2.1.3 色彩空间的转换
- cvtColor(img, colorspace): 颜色转换的关键API
import cv2
def callback(value):
pass
cv2.namedWindow('color', cv2.WINDOW_NORMAL)
cv2.resizeWindow('mouse', 640, 480)
img = cv2.imread('./cat.jpeg')
colorspaces = [cv2.COLOR_BGR2RGBA, cv2.COLOR_BGR2BGRA,
cv2.COLOR_BGR2GRAY, cv2.COLOR_BGR2HSV,
cv2.COLOR_BGR2YUV]
cv2.createTrackbar('curcolor', 'color', 0, 4, callback)
while True:
index = cv2.getTrackbarPos('curcolor', 'color')
cvt_img = cv2.cvtColor(img, colorspaces[index])
cv2.imshow('color', cvt_img)
key = cv2.waitKey(10)
if key & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
2.2 OpenCV的重要数据结构–Mat
2.2.1 Mat介绍
Mat是OpenCV在C++语言中用来表示图像数据的一种数据结构.在python中转化为numpy的ndarray.
- Mat由header和data组成, header中记录了图片的维数, 大小, 数据类型等数据.
2.2.2 Mat拷贝
- Mat共享数据
在python中Mat数据对应numpy的ndarray, 使用numpy提供的深浅拷贝方法即可实现Mat的拷贝.
import cv2
import numpy as np
img = cv2.imread('./cat.jpeg')
img2 = img.view()
img3 = img.copy()
img[10:100, 10:100] = [0, 0, 255]
cv2.imshow('img', img)
cv2.imshow('img2', img2)
cv2.imshow('img3', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.2.3 访问图像(Mat)的属性
OpenCV中的Mat在python中已经转化为ndarray, 通过ndarray的属性即可访问Mat图像的属性
import cv2
import numpy as np
img = cv2.imread('cat.jpeg')
print(img.shape)
print(img.size)
print(img.dtype)
2.2.4 通道的分离与合并
- split(mat)分割图像的通道
- merge((ch1,ch2, ch3)) 融合多个通道
import cv2
import numpy as np
img = np.zeros((480, 640, 3), np.uint8)
b,g,r = cv2.split(img)
b[10:100, 10:100] = 255
g[10:100, 10:100] = 255
img2 = cv2.merge((b, g, r))
cv2.imshow('img', img)
cv2.imshow('b', b)
cv2.imshow('g', g)
cv2.imshow('img2', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.3 绘制图形
利用OpenCV提供的绘制图形API可以轻松在图像上绘制各种图形, 比如直线, 矩形, 圆, 椭圆等图形.
-
line(img, pt1, pt2, color, thickness, lineType, shift) 画直线
- img: 在哪个图像上画线
- pt1, pt2: 开始点, 结束点. 指定线的开始与结束位置
- color: 颜色
- thickness: 线宽
- lineType: 线型.线型为-1, 4, 8, 16, 默认为8
- shift: 坐标缩放比例.
-
rectangle() 参数同上 画矩形 -
circle(img, center, radius, color[, thickness[, lineType[, shift]]]) 中括号内参数表示可选参数. 画圆 -
ellipse(img, 中心点, 长宽的一半, 角度, 从哪个角度开始, 从哪个角度结束,…)
- polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]]) 画多边形
- fillPoly 填充多边形
- putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]) 绘制文本
- text 要绘制的文本
- org 文本在图片中的左下角坐标
- fontFace 字体类型即字体
- fontScale 字体大小
import cv2
import numpy as np
img = np.zeros((480, 640, 3), np.uint8)
cv2.putText(img, "Hello OpenCV!", (10, 400), cv2.FONT_HERSHEY_TRIPLEX, 3, (255,0,0))
cv2.imshow('draw', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
-
绘制中文 opencv本身不支持, 因为没有中文字体.我们可以借助pillow来实现绘制中文
import cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image
img = np.full((200, 200, 3), fill_value=255, dtype=np.uint8)
font_path = 'msyhbd.ttc'
font = ImageFont.truetype(font_path, 15)
img_pil = Image.fromarray(img)
draw = ImageDraw.Draw(img_pil)
draw.text((10, 150), '绘制中文', font=font, fill=(0, 255, 0, 0))
img = np.array(img_pil)
cv2.putText(img, '中文', (10, 100), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 1)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
|