OpenCV入门

OpenCV入门,第1张


一、图像处理基本 *** 作 1.读取图像

使用的方法:imread()

cv.imread(filename[,flags])

参数说明:

📊filename:要读取文件的名称

📊flages:

  • cv.IMREAD_COLOR: 加载彩色图像。


    任何图像的透明度都会被忽视。


    它是默认标志。


  • cv.IMREAD_GRAYSCALE:以灰度模式加载图像
  • cv.IMREAD_UNCHANGED:加载图像,包括alpha通道

注意 除了这三个标志,你可以分别简单地传递整数1、0或-1。


import cv2 as cv

image_1 = cv.imread('1.png', 1)
image_2 = cv.imread("D:\learn\1.png", 1)

3、4行代码效果相同,只不过第四行代码可以读取别的路径下的图片。


2.显示图像

使用的方法:imshow()waitkey()destroyAllWindows()

  1. imshow():显示图像

    cv.imshow(winname,mat)

    参数说明:

    📊 winname:显示图像窗口的名称

    📊 mat:要显示的图像

  2. waitKey():等待用户按下键盘按键的时间。


    当用户按下键盘的任意按键时,将执行waitKey() 方法,并且获取此方法的返回值。


    retval = cv.waitKey(delay)

    参数说明:

    📊 retval:与被按下键相对应的ASCII码。


    例如ESC键的ACSII码为27,当用户按下ESC键时,waitKey()方法返回值时27,如果不是就返回-1。


    📊 delay:等待用户按下键盘上按键的时间。


    单位为ms,如果值为负数,0或者为空时表示无限等待。


  3. destroyAllWindows():销毁正在显示图像的窗口

    cv.destroyAllWindows()

实例:

import cv2 as cv

image = cv.imread('1.png', 1)

cv.imshow("taylor", image)
retval = cv.waitKey()
cv.destroyAllWindows()

print(retval)

运行结果:按下ESC

27

注意:

1️⃣窗口的名称不能为中文,否则会出现乱码。


2️⃣为了能够正常显示图像,cv.waitKey()不能省略,否则图像会一闪而过。


补充:

1️⃣cv.destroyWindow():销毁指定名称的窗口。


import cv2 as cv

image = cv.imread('1.png', 1)

cv.imshow("taylor", image)
retval = cv.waitKey()
cv.destroyWindow("taylor")

print(retval)

2️⃣在特殊情况下,用户可以先创建一个空窗口,然后再将图像传入窗口。


这种情况下可以指定窗口的大小。


这是通过cv.nameWindow()完成的。


默认情况下,该标志为cv.WINDOW_AUTOSIZE,但是如果将标志指定为cv.WINDOW_NORMAL就可以调整窗口的大小。


实例:

import cv2 as cv

image = cv.imread("1.png")
cv.namedWindow("taylor", cv.WINDOW_NORMAL)
cv.imshow("taylor", image)
cv.waitKey()
cv.destroyAllWindows()

运行结果:窗口是可以用鼠标调整大小的

注意

代码的第3,4行要显示的窗口名称必须保持一致,否则会出现两个窗口。


3.保存图像

使用方法:imwrite():可用于按照指定路径保存图像。


cv.imwrite(filename,img)

参数说明:

📊filename:保存图像的完整路径。


📊img:要保存的图像。


实例:

import cv2 as cv

image = cv.imread("1.png", 0)
cv.namedWindow("taylor", cv.WINDOW_NORMAL)
cv.imshow("taylor", image)
cv.imwrite("D:\learn\2.png", image)
cv.waitKey()
cv.destroyAllWindows()

运行结果:

4.图像属性

使用方法:shape、size、dtype

1️⃣shape:如果图像是彩色图像,那么获取的是一个由图像的像素列数,行数和通道数组成的数组;

​ 如果图像是灰度图像,那么获取的是一个由图像的像素列数,行数组成的数组。


2️⃣size:获取的是一个包含图像的像素个数,值大小等于像素列数×像素行数×通道数(如果是灰度图像,通道数就是1)。


3️⃣dtype:获取的是图像的数据类型。


import cv2 as cv

image = cv.imread("1.png")
print("图像的色彩属性:")
print("shape = ", image.shape)
print("size = ", image.size)
print("dtype = ", image.dtype)

运行结果:

图像的色彩属性:
shape =  (1080, 1920, 3)
size =  6220800
dtype =  uint8

二、图像数字化基础

图像数字化指的是用数字表示图像。


计算机通常会把像素值处理为处理为256个灰度级别,这256个灰度级别分别用区间[0,255]中的数值表示。


其中0表示纯黑色,255表示纯白色。


1.像素

像素是构成数字图像的基本单位。


  1. 确定像素的位置

    首先要确定此图像水平方向和垂直方向上的像素个数。


在OpenCV中正确表示某个像素坐标的表示方法是(y,x)。


实例:

import cv2 as cv

image = cv.imread("1.png")
px = image[1079, 1919]
  1. 获取像素的BGR值

    上一小节已经获取了坐标为[1079,1919]上的像素px,那么使用print()方法打印这个像素得到的就是这个像素BGR值。


    import cv2 as cv
    
    image = cv.imread("1.png")
    px = image[1079, 1919]
    print("这个像素的BGR值为", px)
    

    运行 结果为:

    这个像素的BGR值为 [179 177 177]
    

    在了解这三组数字代表的含义之前,先了解一下何为三基色。


    人眼能感受到红色、绿色和蓝色三种颜色,把这三种颜色称为三基色,同时将三基色以不同比例混合就可以得到不同的颜色。


    那么在计算机中要对颜色进行编码,就要使用到色彩空间。


    其中较为常用的就是RGB色彩空间。


    以此为例,在RGB色彩空间中,有三个颜色通道,分别是:红色R、绿色G和蓝色B。


    并且每个颜色都在[0,255]之间取值。


    不过需要注意的是,OpenCV在输出通道顺序的时候是相反的,是按照BGR输出。


    在OpenCV中获取像素的BGR值方法有两种:

    import cv2 as cv
    
    image = cv.imread("1.png")
    px = image[1079, 1919]
    print("这个像素的BGR值为", px)
    
    import cv2 as cv
    
    image = cv.imread("1.png")
    print("这个像素的B值为", image[1079, 1919, 0])
    print("这个像素的G值为", image[1079, 1919, 1])
    print("这个像素的R值为", image[1079, 1919, 2])
    

    运行结果:
    参考前文程序输出。


  2. 修改像素的BGR值

    前一节获得了坐标为[1079,1919]的像素的BGR值,如果要修改BGR值,代码为:

    import cv2 as cv
    
    image = cv.imread("1.png")
    px = image[1079, 1919]
    print("这个像素修改前的BGR值为", px)
    px = [255, 255, 255]
    print("这个像素修改后的BGR值为", px)
    

    运行结果:

    这个像素修改前的BGR值为 [179 177 177]
    这个像素修改后的BGR值为 [255, 255, 255]
    

    注意:

    如果将每个像素的R、G、B值改为相等大小时,就可以得到灰度图像。


    全为0时就是纯黑色,全为255时就是纯白色。


    如果要修改指定区域中的所有像素就可以使用2层for循环嵌套:

    import cv2 as cv
    
    image = cv.imread("1.png", 1)
    cv.namedWindow("taylor", cv.WINDOW_NORMAL)
    
    for i in range(0, 79):
        for j in range(0, 19):
            image[i, j] = [0, 0, 0]
    
    cv.imshow("taylor", image)
    cv.waitKey()
    cv.destroyAllWindows()
    
    

    运行结果:


⚠️ 警告

文章刚开头介绍了imread()方法,前一节介绍了如何修改指定区域的元素。


比较下面图片中代码的区别:

如果图片是以彩色图像 加载的时候,那么修改指定区域像素的颜色,可以直接使用列表[0,0,0]

如果图像不是以彩色图像加载的时候,那么修改指定区域像素的颜色,不能直接使用列表[0,0,0],否则会报错:ValueError: setting an array element with a sequence.必须要使用数组。


Numpy是用于快速数组计算的优化库。


因此,简单地访问每个像素值并对其进行修改将非常缓慢,因此不建议使用。


注意 上面的方法通常用于选择数组的区域,例如前5行和后3列。


对于单个像素访问,Numpy数组方法array.item()和array.itemset())被认为更好,但是它们始终返回标量。


如果要访问所有B,G,R值,则需要分别调用所有的array.item()。


更好的像素访问和编辑方法:

# 访问 RED 值
>>> img.item(10,10,2)
59
# 修改 RED 值
>>> img.itemset((10,10,2),100)
>>> img.item(10,10,2)
100

2.色彩空间

除了前文介绍的RGB和BGR色彩空间,还有两个比较常见的色彩空间:GRAY和HSV色彩空间。


1.GRAY色彩空间

GRAY色彩空间通常指的是灰度图像,每个像素都是从黑到白([0,255]).0表示纯黑色,255表示纯白色。


2.从RGB/BGR色彩空间到GRAY色彩空间

使用方法:dst = cv.cvtColor(src,code)

参数说明:

📊dst:转换后的图像;

📊src:转换前的初始图像

📊code:色彩空间转换码

色彩空间转换码含义
cv.COLOR_BGR2GRAY从BGR色彩空间转换到GRAY色彩空间
cv.COLOR_RGB2GRAY从RGB色彩空间转换到GRAY色彩空间

实例:

import cv2 as cv

image = cv.imread("1.png", 1)
image_GRAY = cv.cvtColor(image, cv.COLOR_BGR2GRAY)

cv.imshow("taylor", image_GRAY)
cv.waitKey()
cv.destroyAllWindows()

1️⃣色彩空间转换码还有很多,读者请自行查阅。


2️⃣虽然色彩空间转换是双向的,但是灰度图像是无法转换成彩色图像的。


因为彩色图像在转换成灰度图像的时候丢失了颜色比例,并且无法找回。


3.HSV色彩空间

HSV色彩空间是基于色调、饱和度、亮度而言的。


色调 H 指的是光的颜色。


在OpenCV中,色调在[0,180]内取值。


红、黄、绿和蓝分别是:0、30、60、120。


饱和度 S 指的是色彩的深浅。


在OpenCV中,饱和度在[0,255]内取值。


饱和度为0时,图像将变为灰度图像。


亮度 V 指的是光的明暗。


在OpenCV中,亮度在[0,255]内取值。


实例:

import cv2 as cv

image = cv.imread("1.png", 1)
image_GRAY = cv.cvtColor(image, cv.COLOR_BGR2HSV)

cv.imshow("taylor", image_GRAY)
cv.waitKey()
cv.destroyAllWindows()

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qWW2H1Si-1649246389207)(D:\learn\opencv入门.assets\image-20220406101443885.png)]

3.通道

1.拆分通道

使用方法:split()

b,g,r = cv.split(bgr_image)

参数说明:

📊b:B通道图像

📊g:G通道图像

📊R:R通道图像

📊bgr_image:一幅RGB图像

拆分一幅BGR图像通道的顺序是B→G→R,因此等号左边必须是“b, g, r”。


实例:

import cv2 as cv

image = cv.imread("1.png", 1)
b, g, r = cv.split(image)

cv.namedWindow("taylor", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_B", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_G", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_R", cv.WINDOW_NORMAL)

cv.imshow("taylor", image)
cv.imshow("taylor_B", b)
cv.imshow("taylor_G", g)
cv.imshow("taylor_R", r)

cv.waitKey()
cv.destroyAllWindows()

运行结果:

有的读者会发现得到的B、G、R通道图像是3幅不同灰度的图像。


这是因为在cv.imshow("taylor_B",b)时候,BGR这三通道的值都为B通道的值。


其余两个同理。


所以只要 B=G=R 就可以得到灰度图像。


实例:

import cv2 as cv

image = cv.imread("1.png", 1)
b, g, r = cv.split(image)


cv.namedWindow("taylor", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_B", cv.WINDOW_NORMAL)


for i in range(0, 1079):
    for j in range(0, 1919):
        a = image[i, j]
        image[i, j] = a[0]

cv.imshow("taylor", image)
cv.imshow("taylor_B", b)


cv.waitKey()
cv.destroyAllWindows()

运行结果:

拆分一幅图像的HSV通道。


只需先将图像先转换为HSV图像即可,后面步骤一致。


实例:

import cv2 as cv

image = cv.imread("1.png", 1)
image_HSV = cv.cvtColor(image, cv.COLOR_BGR2HSV)
h, s, v = cv.split(image_HSV)

cv.namedWindow("taylor", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_H", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_S", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_V", cv.WINDOW_NORMAL)

cv.imshow("taylor", image_HSV)
cv.imshow("taylor_H", h)
cv.imshow("taylor_S", s)
cv.imshow("taylor_V", v)

cv.waitKey()
cv.destroyAllWindows()

运行结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v7fPJp6E-1649246389208)(D:\learn\opencv入门.assets\image-20220406183300394.png)]

2.合并通道

合并通道是拆分通道的逆过程。


使用方法:bgr = cv.merge([b,g,r])

参数说明:

📊bgr:按照B→G→R的顺序合并后得到的图像。


📊b:B通道图像

📊g:G通道图像

📊r:R通道图像

如果用户要按照R→G→B顺序合并,调换顺序即可。


实例:

import cv2 as cv

image = cv.imread("1.png", 1)
b, g, r = cv.split(image)
cv.namedWindow("taylor_original", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_merge_BGR", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_merge_RGB", cv.WINDOW_NORMAL)

cv.imshow("taylor_original", image)
image_merge_BGR = cv.merge([b, g, r])
image_merge_RGB = cv.merge([r, g, b])
cv.imshow("taylor_merge_BGR", image_merge_BGR)
cv.imshow("taylor_merge_RGB", image_merge_RGB)

cv.waitKey()
cv.destroyAllWindows()

运行结果:

相信读者已经发现,按照不同的合并顺序得到的图像也是不一样的。


HSV通道合并同理。


不多赘述。


3.合理运用拆分通道和合并通道
在HSV色彩空间内,如果保持其中两个通道的值不变,调整第三个通道,会得到相应的艺术效果。


**实例:**只把H通道的值改为180

import cv2 as cv

cv.namedWindow("taylor_H180", cv.WINDOW_NORMAL)
image = cv.imread("1.png", 1)

image_HSV = cv.cvtColor(image, cv.COLOR_BGR2HSV)

h, s, v = cv.split(image_HSV)

h[:] = 180

image_HSV_merge = cv.merge([h, s, v])

image_HSV2BGR = cv.cvtColor(image_HSV_merge, cv.COLOR_HSV2BGR)

cv.imshow("taylor_H180", image_HSV2BGR)

cv.waitKey()
cv.destroyAllWindows()

运行结果:

⁉️疑问

前一段程序中的第十行做出以下变动:

代码变换前后,输出图片的效果是一样的???

使用type()查看 h 数据类型的时候发现其类型是,不是list。


4.alpha通道

前文说明了BGR色彩空间包含了3个通道,在此基础上再加上一个A通道就构成了alpha色彩空间(BRGA色彩空间)。


A用于设置图像的透明度。


A在区间[0,255]内取值。


0表示纯透明。


实例:

import cv2 as cv

cv.namedWindow("taylor_BGRA_A200", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_BGRA", cv.WINDOW_NORMAL)

image = cv.imread("1.png", 1)

image_BRGA = cv.cvtColor(image, cv.COLOR_BGR2BGRA)

b, g, r, a = cv.split(image_BRGA)
a[:] = 200

image_BRGA_A200 = cv.merge([b, g, r, a])

cv.imshow("taylor_BGRA_A200", image_BRGA_A200)
cv.imshow("taylor_BGRA", image_BRGA)

cv.waitKey()
cv.destroyAllWindows()

运行结果:

虽然从输出的图片看不出区别,但是将这两幅图使用imwrite()就可以看出区别:

实例:

import cv2 as cv

cv.namedWindow("taylor_BGRA_A200", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_BGRA", cv.WINDOW_NORMAL)

image = cv.imread("1.png", 1)

image_BGRA = cv.cvtColor(image, cv.COLOR_BGR2BGRA)

b, g, r, a = cv.split(image_BGRA)
a[:] = 200

image_BGRA_A200 = cv.merge([b, g, r, a])

cv.imshow("taylor_BGRA_A200", image_BGRA_A200)
cv.imshow("taylor_BGRA", image_BGRA)

cv.imwrite("D:/learn/taylor_BGRA_A200.png", image_BGRA_A200)
cv.imwrite("D:/learn/taylor_BGRA.png", image_BGRA)

cv.waitKey()
cv.destroyAllWindows()

运行结果:

由于后面的相关学习需要用到Numpy,作者先去更新Numpy相关学习内容了。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/570854.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-09
下一篇 2022-04-09

发表评论

登录后才能评论

评论列表(0条)

保存