当前位置:网站首页>【 2 】 OpenCV image processing: basic knowledge of OpenCV
【 2 】 OpenCV image processing: basic knowledge of OpenCV
2022-08-05 02:19:00 【LeoATLiang】
文章目录
二、OpenCV 基础知识
1、OpenCV 的色彩空间
1.1 RGB 和 BGR
最常见的色彩空间就是RGB,人眼也是基于RGB的色彩空间去分辨颜色的.OpenCV 默认使用的是BGR.
RGB和BGR色彩空间的区别在于图片在色彩通道上的排列顺序不同.
1、RGB 如下图所示:
2、BGR 如下图所示:
Be careful when displaying pictures适配图片color space and 显示环境的色彩空间.
比如传入的图片是BGR色彩空间,显示环境是RGB色彩空间,就会出现颜色混乱的情况.
1.2 HSV、HSL 和 YUV
1、HSV(HSB)
- Hue:色相,即色彩,如红色、绿色、蓝色.
- 用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°.
- 它们的补色是:黄色为60°,青色为180°,紫色为300°.
- Saturation:饱和度,表示颜色接近光谱色的程度.
- 一种颜色,可以看成是某种光谱色与白色混合的结果.
- 其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高.
- 饱和度高,颜色则深而艳.
- 光谱色的白光成分为0,饱和度达到最高.
- 通常取值范围为0%~100%,值越大,颜色越饱和.
- 一种颜色,可以看成是某种光谱色与白色混合的结果.
- Value(Brightness):明度,表示颜色明亮的程度.
- 对于光源色,明度值与发光体的光亮度有关;
- 对于物体色,This value is related to the transmittance or reflectance of the object.
- 通常取值范围为0%(黑)~100%(白).
OpenCV用的最多的色彩空间是HSV.
2、HSL
HUE:色相,色彩的基本属性,就是平常所说的颜色名称.如红色、黄色等.
Saturation:色彩的纯度,越高色彩越纯,低则逐渐变灰,取0%~100%的数值.
Lightness:亮度,取0%~100%
3、HSV 和 HSL 的区别:
4、YUV
YUV,是一种颜色编码方法.常使用在各个视频处理组件中. YUV在对照片或视频编码时,考虑到人类的感知能力,允许降低色度的带宽.
“Y”表示明亮度(Luminance或Luma),也就是灰阶值,“U”和“V”表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色.
YUV的发明是由于彩色电视与黑白电视的过渡时期.
黑白视频只有Y(Luma,Luminance)视频,也就是灰阶值.到了彩色电视规格的制定,是以YUV/YIQ的格式来处理彩色电视图像,把UV视作表示彩度的C(Chrominance或Chroma),如果忽略C信号,那么剩下的Y(Luma)信号就跟之前的黑白电视频号相同,这样一来便解决彩色电视机与黑白电视机的兼容问题.
YUV最大的优点在于只需占用极少的带宽.
为节省带宽起见,大多数YUV格式平均使用的每像素位数都少于24位.主要的抽样(subsample)格式有YCbCr4:2:0、YCbCr4:2:2、YCbCr4:1:1和YCbCr4:4:4.YUV的表示法称为A:B:C表示法:
- 4:4:4表示完全取样.
- 4:2:2表示2:1的水平取样,垂直完全采样.
- 4:2:0表示2:1的水平取样,垂直2:1采样.
- 4:1:1表示4:1的水平取样,垂直完全采样.
1.3 色彩空间的转换
1.3.1 cvtColor() 颜色转换
cvtColor()
用法:
cv2.cvtColor(img, colorspace)
参数说明:
- img:需要转换的图像
- colorspace:What format to convert the image to
cv2.COLOR_BGR2RGBA
是将BGR格式转换为RGBA格式
1.3.2 代码实现
import cv2
def callback(value):
print(value)
cv2.namedWindow('color', cv2.WINDOW_NORMAL)
cv2.resizeWindow('color', 640, 480)
# OpenCV读取的图像默认是BGR的色彩空间
img = cv2.imread('../resource/dog.jpg')
# Defines a list of color space conversions 2 = to
color_spaces = [
cv2.COLOR_BGR2RGBA, cv2.COLOR_BGR2BGRA,
cv2.COLOR_BGR2GRAY, cv2.COLOR_BGR2HSV,
cv2.COLOR_BGR2YUV
]
# 创建Trackbar
cv2.createTrackbar('trackbar', 'color', 0, 4, callback)
while True:
# 获取当前Trackbar值
index = cv2.getTrackbarPos('trackbar', 'color')
# 颜色空间转换API
cvt_img = cv2.cvtColor(img, color_spaces[index])
cv2.imshow('color', cvt_img)
key = cv2.waitKey(10)
if key & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
2、Numpy 基本操作
Numpy是一个经高度优化的Python数值库.OpenCV中用到的矩阵都要转换成Numpy数组,然后再进行后续操作.
在使用Numpywhen performing basic operations,都需要导入Numpy库,即import numpy as np
.
2.1 创建矩阵
1、创建数组 array()
- 一维数组
a = np.array([1, 2, 3])
- 二维数组
b = np.array([[1, 3, 5], [2, 4, 6]])
2、创建全 0 / 1 数组 zeros() / ones()
zeros()
用法:
c = np.zeros((480, 640, 3), np.uint8)
参数说明:
- (480, 640, 3):(行的个数, 列的个数, 通道数/层数)
- np.uint8:矩阵中的数据类型
实例1:4 * 4 * 3(方便演示)
c = np.zeros((4, 4, 3), np.uint8)
print(c)
[[[0 0 0]
[0 0 0]
[0 0 0]
[0 0 0]]
[[0 0 0]
[0 0 0]
[0 0 0]
[0 0 0]]
[[0 0 0]
[0 0 0]
[0 0 0]
[0 0 0]]
[[0 0 0]
[0 0 0]
[0 0 0]
[0 0 0]]]
实例2:4 * 4(The number of channels may not be specified/层数,即默认1通道/层)
c = np.zeros((4, 4), np.uint8)
print(c)
[[0 0 0 0]
[0 0 0 0]
[0 0 0 0]
[0 0 0 0]]
ones()
用法:
d = np.ones((480, 640, 3), np.uint8)
ones() 用法和 zeros() 用法基本一致,其主要区别是:ones() The created array values are all 1 ,而 zeros() The created arrays are all 0 .
3、创建全值数组 full()
full()
用法:
e = np.full((480, 640, 3), 255, np.uint8)
参数说明:
- (480, 640, 3):(行的个数, 列的个数, 通道数/层数)
- 255:表示每个元素的数值
- np.uint8:矩阵中的数据类型
实例1:
e = np.full((4, 4, 3), 255, np.uint8)
print(e)
[[[255 255 255]
[255 255 255]
[255 255 255]
[255 255 255]]
[[255 255 255]
[255 255 255]
[255 255 255]
[255 255 255]]
[[255 255 255]
[255 255 255]
[255 255 255]
[255 255 255]]
[[255 255 255]
[255 255 255]
[255 255 255]
[255 255 255]]]
实例2:Of course, the number of channels may not be specified/层数
e = np.full((4, 4), 255, np.uint8)
print(e)
[[255 255 255 255]
[255 255 255 255]
[255 255 255 255]
[255 255 255 255]]
4、创建单元数组 identity() / eye()
identity()
用法:
f = np.identity(3)
参数说明:
- 3:表示几维数组,即 3 * 3(3行3列)
- The main diagonal is1,其它是0
实例1:3 * 3
f = np.identity(3)
print(f)
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]
实例2:5 * 5
f = np.identity(5)
print(f)
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]]
eye()
用法:
g = np.eye(3, 5, k=3)
参数说明:
- (3, 5):3行5列
- k=3:从下标为3The starting diagonal is 1,其它为0(下标0,1,2,3,…)
实例1:
g = np.eye(3, 5, k=3)
print(g)
[[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]
[0. 0. 0. 0. 0.]]
实例2:如果不指定k或者k为0,The default is to start with one(下标为0)That is, the main diagonal assignment1,其它为0.
g = np.eye(3, 5)
h = np.eye(3, 5, 0)
print(g)
print(h)
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]]
# 效果一样
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]]
2.2 检索与赋值[y, x] / [y, x, channel]
1、检索
- [y, x]
img = np.zeros((480, 640, 3), np.uint8)
print(img[100, 100])
[0 0 0]
- [y, x, channel]
img = np.zeros((480, 640, 3), np.uint8)
print(img[100, 100, 0])
0
channelUsed to specify the number of channels,由于OpenCV默认是BGR三通道,所以取值0,1,2
2、赋值
实例1:img[y, x] = 255
img[count, 100] = 255
不指定channel,默认白色.
实例2:img[y, x] = [B, G, R]
通道组合 [B, G, R] Generally only need to master the following:
- [255, 0, 0]:蓝色通道(B)
- [0, 255, 0]:绿色通道(G)
- [0, 0, 255]:红色通道
- [255, 255, 255]:白色(混合)
img[count, 100] = [0, 0, 255]
img[count, 100] = [255, 255, 255]
实例3:img[y, x, channel] = 255
OpenCV默认是BGR三通道,所以channel可以取0、1或2,即:
- channel = 0:蓝色通道(B)
- channel = 1:绿色通道(G)
- channel = 2:红色通道
img[count, 100, 0] = 255
代码实现(完整)
import cv2
import numpy as np
img = np.zeros((480, 640, 3), np.uint8)
# Read the value of an element from a matrix
print(img[100, 100])
print(img[100, 100, 1])
count = 0
# Assign a value to an element in a matrix
while count < 200:
# img[count, 100] = 255
# img[count, 100, 0] = 255
img[count, 100] = [255, 255, 255]
count += 1
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.3 获取子矩阵[:, :]
1、[y1: y2, x1: x2]
获取像素点x1~x2,y1~y2的区域.
2、[:, :]
或 [:]
Get all pixels.
import cv2
import numpy as np
img = np.zeros((480, 640, 3), np.uint8)
roi = img[100:400, 100:600]
# roi[:, :] = [0, 0, 255]
roi[:] = [0, 0, 255]
roi[10:200, 10:200] = [0, 255, 0]
cv2.imshow('img', roi)
cv2.waitKey(0)
cv2.destroyAllWindows()
3、OpenCV 的重要数据结构—Mat
3.1 Mat 介绍
Mat是OpenCV在 C++ 语言中用来表示图像数据的一种数据结构,在 Python 中转换为numpy的ndarray.
- Mat由header和data组成,header中记录了图片的维数、Data such as size and data type.
- Mat在C++中的原型:
class CV_EXPORTS Mat{
public:
...
int dims; //维数
int rows, cols; //行、列数
uchar *data; //存储数据的指针
int *refcount; //引用计数
...
};
- Mat属性
字段 | 说明 | 字段 | 说明 |
---|---|---|---|
dims | 维度 | channels | 通道数 RGB是3 |
rows | 行数 | size | 矩阵大小 |
cols | 列数 | type | dep + dt + chs CV_8UC3 |
depth | 像素的位深 | data | 存放数据 |
3.2 Mat 拷贝
MatThe default is shallow copy when copying,只拷贝Header中的内容,数据不变.
1、Mat浅拷贝
Mat A
A = imread(file, IMREAD_COLOR)
Mat B(A)
B 与 A 的 Header 不同,但指向的数据相同,如下代码:
img1 = cv2.imread('../resource/cold.jpg', cv2.IMREAD_COLOR)
img2 = img1
img1[10:100, 10:100] = [0, 0, 255]
2、Mat深拷贝
C++中实现方式有两种:
cv::Mat::clone()
cv::Mat::copyTo()
将 Data 也重新赋值一份,A 与 B 完全切断.
在Python中:
img3 = img1.copy()
进行深拷贝后,The original image is not affected during image processing.
img1 = cv2.imread('../resource/cold.jpg', cv2.IMREAD_COLOR)
img3 = img1.copy()
img1[10:100, 10:100] = [0, 0, 255]
3.3 代码实现
import cv2
img1 = cv2.imread('../resource/cold.jpg', cv2.IMREAD_COLOR)
# 浅拷贝
img2 = img1
# 深拷贝
img3 = img1.copy()
img1[10:100, 10:100] = [0, 0, 255]
cv2.imshow('img1', img1)
cv2.imshow('img2', img2)
cv2.imshow('img3', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.4 访问图像(Mat)的属性
import cv2
img = cv2.imread('../resource/structure.jpg', cv2.IMREAD_COLOR)
方便演示!
1、img.shape
用法:
shape 中包含三个信息:高度、宽度和通道数.
print(img.shape)
(3000, 4500, 3)
i.e. the image(高:3000,宽:4500,通道数:3).
2、img.size
用法:
size i.e. the image takes up space = 高度 * 宽度 * 通道数 .
print(img.size)
40500000
3000 * 4500 * 3 = 40500000
3、img.dtype
用法:
dtype Represents each element in the image位深.
print(img.dtype)
uint8
uint8 表示 8位无符号整型(0~255).
3.5 通道分离与合并
1、split(mat)
: 分离
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
cv2.imshow('img', img)
cv2.imshow('b', b)
cv2.imshow('g', g)
cv2.waitKey(0)
cv2.destroyAllWindows()
2、merge((ch1, ch2, ...))
: 合并
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
img_merge = cv2.merge((b, g, r))
cv2.imshow('img', img)
cv2.imshow('b', b)
cv2.imshow('g', g)
cv2.imshow('img_merge', img_merge)
cv2.waitKey(0)
cv2.destroyAllWindows()
边栏推荐
猜你喜欢
随机推荐
从零到一快速学会三子棋
如何看待自己的羞愧感
RAID disk array
用@Mapper查询oracle的分区情况报错
Leetcode刷题——22. 括号生成
ARM Mailbox
行业案例|世界 500 强险企如何建设指标驱动的经营分析系统
使用SuperMap iDesktopX数据迁移工具迁移地图文档和符号
Xunrui cms website cannot be displayed normally after relocation and server change
leetcode 15
LPQ (local phase quantization) study notes
Understand the recommendation system in one article: Recall 06: Two-tower model - model structure, training method, the recall model is a late fusion feature, and the sorting model is an early fusion
How to create an rpm package
CPDA|运营人如何从负基础学会数据分析(SQL)
C学生管理系统 据学号查找学生节点
Live preview | 30 minutes started quickly!Look at credible distributed AI chain oar architectural design
学习笔记-----左偏树
短域名绕过及xss相关知识
2022 EdgeX中国挑战赛8月3日即将盛大开幕
[ROS] (10) ROS Communication - Service Communication