核心知识
(1)色彩空间变换
(2)像素访问
(3)矩阵的 + - * /
(4)基本图形的绘制
以上的核心知识将会在接下来的部分给大家介绍清楚,并且有实战代码展示。
色彩空间
色彩空间基础知识
(1)RGB:是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色。(简单来说就是人对于颜色的一个识别,当然机器也是这样的)
(2)BGR:Opencv默认使用BGR。
其实对于rgb和bgr来说,就是红绿蓝的排列顺序不同,所以在编写代码时,需要注意顺序问题。
(3)HSV/HSB/HSL: Opencv最常用的就是HSV。H代表色相,S代表饱和度,V/B代表明亮度,HSV与HSB其实是一样的,只是在翻译时不同。
(4)YUV:主要用于视频领域。
RGB和BGR
RGB:每一个方框都代表一个像素 ,每一个像素都是由RGB显示出来的。
BGR:同样与RGB类似,每一个方框都代表一个像素 ,每一个像素都是由BGR显示出来的。
HSV与HSL
HSV相关知识
Hue:色相,即颜色,如红色,蓝色
Saturation:饱和度,颜色的纯度(越大越纯)
Value:明度(越明一点就代表黑色的部分少一点)
对于第一张图,Hue是圆的一周,也就是在不同角度下颜色在发生变化。Saturation是从圆的平面看,从里到外值越来越高,颜色就越来越纯(颜色中灰色的部分越来越少)。Value是从圆柱的高进行观察,从下到上,Value值越来越高,也就越来越亮(黑色的部分越来越少)。
为什么我们使用HSV?
因为相对于RGB来说,HSV的参数更多,我们可以使用HSV来判断色相,饱和度,亮度等等信息。使图片描绘更加准确。
HSL相关知识
Hue:色相,即颜色,如红色,蓝色
Saturation:饱和度,颜色的纯度(越大越纯)
ligthness:明度(越明一点就代表黑色的部分少一点)
左边的使HSL,我们可以发现Hue和Saturation都是相同的,并且高都是亮度,但是HSL从下到上出现最上面的颜色都是白色的现象,这个就是HSL。
相较于我们目前使用的HSV更加重要一点。
YUV
主要用于视频中。
(1)YUV4:2:0
(2)YUV4:2:2
(3)YUV4:4:4
Y代表灰色的图像,UV代表的是颜色 。YUV4:4:4其实就和RGB是一样的,RGB是8:8:8
YUV4:2:0就是四个像素中有4个Y但是后面的2可能是U可能是V
色彩空间转换实战代码
import cv2
def callback1(i):
pass
cv2.namedWindow('color', cv2.WINDOW_AUTOSIZE)
img = cv2.imread('E:\\pycharm\\PycharmFile\\opencv\\MM\\preview.jpg')
colorspaces = [cv2.COLOR_BGR2RGBA, cv2.COLOR_BGR2BGRA,
cv2.COLOR_BGR2GRAY, cv2.COLOR_BGR2HSV,
cv2.COLOR_BGR2YUV]
cv2.createTrackbar('curcolor', 'color', 0, 4, callback1)
while True:
index = cv2.getTrackbarPos('curcolor', 'color')
# print("11111")
# 色彩转化api
cvt_img = cv2.cvtColor(img, colorspaces[index])
cv2.imshow('color', cvt_img)
key = cv2.waitKey(10)
if (key & 0xFF == ord('q')):
break
cv2.destroyAllWindows()
结果显示如下:
通过拖动TrackBar改变颜色显示,例如index为0的时候 cv2.COLOR_BGR2RGBA就是将原来的BGR图片转化为RGB。 其他情况和这种类似。
Numpy库
图像的加减乘除都与这个函数密切相关
Numpy库的相关知识
(1)Opencv中使用到的矩阵都需要转化为Numpy数组
(2)Numpy是一个高度优化的Python数值库
Numpy基本操作
(1)创建矩阵:大家都知道图形的处理其实就是矩阵的处理。说的简单点,就一个宽多少高多少的一个矩阵,每个矩阵值就是一个像素点,那你只要改变其中的值,它这个颜色就发生变化。在它周围做一些处理的话,就会形成一个形状,如果把矩阵中的所有的位置都经过特殊处理的话,那它就成了一幅图片。如果把这些图片再连在一起播放的话,它就成了视频,这个就是一个基本的原理。
(2)检索与赋值:我们要能够知道如何获取矩阵中某个元素的值。并且改变这个元素的值。
(3)获取子数组:要获取大的矩阵中的某一小块儿矩阵,或者是给这一小块矩阵赋值。
创建矩阵API:创建数组array(),创建全0或者全1的数组 zeros()/ones(),创建一个全值的数组 full()矩阵中所有的值都是指定的值,创建单位矩阵identity/eye()
检索矩阵API:[y,x] 下标是y和x,索引值是从0开始的。[y,x,channel] channel通道数,也可以认为是层数。
获取子矩阵API:[y1:y2,x1:x2] y1到y2范围和x1到x2范围。[:,:] 对整个矩阵进行操作
Numpy实战代码
创建矩阵
array:a=array([2,3,4])这样得到的就是一个一维的数组
b=array([[2,3,4],[1,2,3]])这样得到了一个2x3的矩阵
import numpy as np
import cv2
# 通过array建立矩阵
a = np.array([1, 2, 3])
b = np.array([[1, 2, 3], [1, 2, 3]])
print(a)
print(b)
打印出的结果:
c=np.zeros((480,640,3),np.uint8) 打印出的是640x480
(480,640,3)(行的个数,列的个数,通道数/层数)
np.uint8 矩阵中的数据类型
# 定义zeros矩阵
c = np.zeros((8, 8, 3), np.uint8) # ((行的个数(高),列的个数(宽),层数),np.uint8代表的是八位元素,最大值为255)
print(c)
d=np.ones((480,640,3),np.uint8) 打印出的是640x480
(480,640,3)(行的个数,列的个数,通道数/层数)
np.uint8 矩阵中的数据类型
# 定义ones矩阵
d = np.ones((8, 8), np.uint8)
print(d)
e=np.full((480,640,3),255,np.uint8) 其中255就是我们向矩阵中添加的值
(480,640,3)(行的个数,列的个数,通道数/层数)
np.uint8 矩阵中的数据类型
# 定义full矩阵
e = np.full((8, 8), 255, np.uint8)
print(e)
f=np.identity(3)
斜对角都是1,其余都是0 。括号中的3代表3x3的矩阵。
# 定义单位矩阵indentity
f = np.identity(4) # 4x4的单位矩阵
print(f)
打印出的结果:
g= np.eye((3,5),k=3) 与单位矩阵类似,但是可以说是长方形的
# 定义eye
g = np.eye(4) # 退化成identity矩阵了 4x4
h = np.eye(4, 5, k=2) # 4x5 第一个1是从第3列开始往下斜
print(g)
print(h)
打印出的结果 :
检索矩阵
在创建的矩阵中检索出某个值
img = np.zeros((480, 640, 3), np.uint8) # 在(480,480)时,打印的就是一个0 (480,480,3),打印是三个0
# 从矩阵中读某个元素的值
print(img[100, 100])
也可以对这个检索到的值进行修改,如果修改的是一个范围上的值,就可以清晰看出图像出现变化,由于我们创建的是一个480x640的全0的图,为黑色。对部分范围值进行修改,图片出现变化。
count = 0
# 向矩阵中某个元素赋值
while count < 300:
# BGR
img[count, 100, 0] = 255 # 如果三次情况下[count,100]就是三层都变 [count,100,0]第一层变 按照bgr色彩变化
# img[count,100]=[255,0,0] #和上面赋值结果相同
count = count + 1
运行结果就是在黑色背景下,第一层颜色变化,第一层是蓝色,所以出现下面的图像。
获取子矩阵
roi = img[100:400, 100:600]
roi[:, :] = [0, 0, 255] # [:,:] 代表全部变化
# roi[:]=[0,0,255] 和上面的一样 代表全部
roi[10:200, 10:300] = [0, 255, 0]
roi[200:280, 300:480] = [255, 0, 0]
cv2.imshow('roi', roi)
首先我们在原来的图片中取[100:400, 100:600]这个范围变成我们的子矩阵,接着对子矩阵进行全面的赋值,变成红色,随后在子矩阵中选择两个区域变换颜色,结果如下图。
最重要的结构体Mat
Mat的相关知识
Mat是什么?
从应用的角度,实际上Mat就是一个矩阵。矩阵可能含有多个通道,如果是一个通道的话,它就是灰色的,只有黑白两种颜色,就是一个二维矩阵。如果是全真色的,它就是一个三个通道的,矩阵包括了这个bgr 3种颜色,通过这种三种颜色可以组合中任何的颜色。
Mat有什么好处?
可以通过Numpy直接通过矩阵的形式对他进行访问。操作方便。
Mat的组成
Mat由header和data组成,data中包含的就是存放图像的具体数值。
header包括一些属性,属性包括:维数,行列数,存储数据的指针,引用数据(也就是说。每一次就同一张图片,通过不同的变量去引用它的时候呢,实际它修改的都是同一块数据。)
Mat的拷贝
从图中了解,我们对MatA进行拷贝为MatB,此时我们的数据其实没有进行拷贝的,只是将header部分进行拷贝,当我想调用data中的数据时,可以使用MatB的header指向data得到想要的数据,此种拷贝方式为浅拷贝(默认拷贝就是浅拷贝)
浅拷贝
Mat A
A=imread(file,IMREAD_COLOR)
Mat B(A)
这样就完成了对A的浅拷贝
深拷贝
cv::Mat:;clone()
cv::Mat::copyTo()
这样就完成了对A的深拷贝
在python中的方法就是 copy()
Mat拷贝实战代码
import cv2
import numpy as np
img = cv2.imread('E:\\pycharm\\PycharmFile\\opencv\\MM\\preview.jpg')
# 浅拷贝
img2 = img
# 深拷贝
img3 = img.copy()
# 对图像进行修改
img[0:100, 0:100] = [0, 0, 255]
cv2.imshow('img', img)
cv2.imshow('img2', img2)
cv2.imshow('img3', img3)
cv2.waitKey()
我们写完代码后思考,img我时拿到了一个图片,通过img对img2进行浅拷贝,那我如果对img图片进行修改的话,img2也会一起发生改变。而img3是深拷贝,应该不会发生变化。接下来观察结果。
我们可以发现,如我们想的那样,img2和img发生了同样的变化,而img3没有发生变化。
访问图像(Mat)的属性实战代码
访问图像的属性在python直接使用shape就可以得到结果了。shape属性中包括了高度,宽度,通道数三个属性,size属性可以知道图像占用的空间大小,dtype属性可以知道每个元素的位深。
import cv2
import numpy as np
img = cv2.imread('E:\\pycharm\\PycharmFile\\opencv\\MM\\preview.jpg')
# shape 属性中包括了 高度 宽度 通道数 三个属性
# 高度 宽度 通道数
print(img.shape)
# 图像占用多大空间
# 高度*宽度*通道数
print(img.size)
# 图像中每个元素的位深
print(img.dtype) # uint8
图像通道分离与合并
图像通道分离与合并API
分离:spit(mat)
合并:merge((ch1,ch2,……))
图像通道分离与合并实战代码
import cv2
import numpy as np
img = np.zeros((480, 460, 3), np.uint8)
b, g, r = cv2.split(img)
b[10:100, 10:100] = 255
g[60:150, 60:150] = 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)
从代码中可以思考,自己先创建了一个黑色的480x460的图片,通过split对其进行分离成3个图,分别对其中两个图的部分进行修改,变化的部分变成了白色。最后又将三张图合并在一起,分别变化的部分依旧保留。结果如下显示。
文章来源:https://www.toymoban.com/news/detail-775906.html
我们发现,合并完后原先变化的部分是白色255,但是现在变成了蓝色和绿色,并且相交的部分颜色变成青色,这个是因为本身我们设置图片是三层的BGR,分别开处理时每一层就是一个单通道的0-255,但是合在一起又恢复成三通道了,颜色也就显现出来了。文章来源地址https://www.toymoban.com/news/detail-775906.html
到了这里,关于opencv必会基础知识的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!