【OpenCV图像处理2】OpenCV 基础知识

简介: 【OpenCV图像处理2】OpenCV 基础知识

二、OpenCV 基础知识

1、OpenCV 的色彩空间

1.1 RGB 和 BGR

最常见的色彩空间就是RGB,人眼也是基于RGB的色彩空间去分辨颜色的。OpenCV 默认使用的是BGR

RGB和BGR色彩空间的区别在于图片在色彩通道上的排列顺序不同

1、RGB 如下图所示:

2、BGR 如下图所示:

显示图片的时候需要注意适配图片的色彩空间和显示环境的色彩空间。

比如传入的图片是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):明度,表示颜色明亮的程度。
  • 对于光源色,明度值与发光体的光亮度有关;
  • 对于物体色,该值和物体的透射比或反射比有关。
  • 通常取值范围为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:将图像转换成何种格式

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')
# 定义颜色空间转换列表 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数组,然后再进行后续操作。

在使用Numpy进行基本操作时,都需要导入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(可以不指定通道数/层数,即默认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() 创建的数组值都为 1 ,而 zeros() 创建的数组都为 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:当然也可以不指定通道数/层数

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列)
  • 主对角线是1,其它是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:从下标为3开始的对角线为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,则默认从一个开始(下标为0)也就是主对角线赋1,其它为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

channel用来指定通道数,由于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] 一般只需掌握以下几种:

  • [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)
# 从矩阵中读取某个元素的值
print(img[100, 100])
print(img[100, 100, 1])
count = 0
# 向矩阵中某个元素赋值
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、[:, :][:] 获取所有像素点。

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中记录了图片的维数、大小和数据类型等数据。

  • 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 拷贝

Mat拷贝时默认为浅拷贝,只拷贝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()

进行深拷贝后,进行图片处理时不影响原图片。

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)

即该图像(高:3000,宽:4500,通道数:3)。

2、img.size用法:

size 即图像占用空间 = 高度 * 宽度 * 通道数

print(img.size)
40500000

3000 * 4500 * 3 = 40500000

3、img.dtype用法:

dtype 表示图像中每个元素的位深

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()

目录
相关文章
|
3月前
|
算法 计算机视觉
基于qt的opencv实时图像处理框架FastCvLearn实战
本文介绍了一个基于Qt的OpenCV实时图像处理框架FastCvLearn,通过手撕代码的方式详细讲解了如何实现实时人脸马赛克等功能,并提供了结果展示和基础知识回顾。
154 7
|
2月前
|
机器学习/深度学习 算法 计算机视觉
【Python篇】Python + OpenCV 全面实战:解锁图像处理与视觉智能的核心技能
【Python篇】Python + OpenCV 全面实战:解锁图像处理与视觉智能的核心技能
116 2
WK
|
4月前
|
计算机视觉 Python
如何使用OpenCV进行基本图像处理
使用OpenCV进行基本图像处理包括安装OpenCV,读取与显示图像,转换图像颜色空间(如从BGR到RGB),调整图像大小,裁剪特定区域,旋转图像,以及应用图像滤镜如高斯模糊等效果。这些基础操作是进行更复杂图像处理任务的前提。OpenCV还支持特征检测、图像分割及对象识别等高级功能。
WK
57 4
|
7月前
|
人工智能 计算机视觉 Python
【OpenCV】计算机视觉图像处理基础知识(上)
【OpenCV】计算机视觉图像处理基础知识(上)
|
7月前
|
算法 计算机视觉
【OpenCV】计算机视觉图像处理基础知识(下)
【OpenCV】计算机视觉图像处理基础知识(下)
|
7月前
|
机器学习/深度学习 人工智能 机器人
【opencv】计算机视觉基础知识
【opencv】计算机视觉基础知识
|
7月前
|
机器学习/深度学习 算法 Linux
使用OpenCV在Python中进行图像处理
使用OpenCV在Python中进行图像处理
|
7月前
|
机器学习/深度学习 API vr&ar
Qt, OpenCV与OpenGL协同作战:图像处理与三维图形界面的完美结合
Qt, OpenCV与OpenGL协同作战:图像处理与三维图形界面的完美结合
1085 4
|
7月前
|
算法 安全 机器人
最新版opencv4.9安装介绍,基本图像处理详解
最新版opencv4.9安装介绍,基本图像处理详解
354 0
|
7月前
|
机器学习/深度学习 存储 算法
OpenCV与NumPy:图像处理中的黄金组合
【4月更文挑战第17天】OpenCV和NumPy是Python图像处理的两大利器,互补协作形成黄金组合。OpenCV专注计算机视觉,提供丰富算法,而NumPy擅长数值计算和数组操作。两者无缝对接,共同实现高效、灵活的图像处理任务。通过灰度化、二值化、边缘检测等案例,展示了它们的协同作用。未来,这一组合将在计算机视觉和机器学习领域发挥更大作用,解锁更多图像处理潜力。