Opencv图像处理系列 ——1.图像的基本操作

本文介绍了计算机对图像的基本操作,包括彩色图像和灰度图像的概念,使用Python的OpenCV库进行图像读取、显示、截取、色彩通道提取、图像扩充、数值计算、图像融合及保存。此外,还讨论了视频处理的基础知识,如读取视频并转换为灰度视频。
摘要由CSDN通过智能技术生成

1.计算机眼中的图像

彩色图像

人看到的彩色图片,反映到大脑,是光影彩色的组合,而计算机看到的图片,却是RGB亮度矩阵。在计算机眼中,图像是以数字矩阵的形式存储的,一张图片被分成了若干个细微的小方格,最小单元的小方格叫做一个像素点,像素点有对应的值,在计算机中像素点的值在0,255之间,数字越大表示这个像素点越亮,一张彩色的图片有R、G、B三个颜色通道,每个通道上像素点的值代表该通道上的亮度。对于灰度图也就是黑白图来说他只有一个颜色通道,一张图片的维度可以表示为【h,w,c】其中h代表高度方向的像素点个数,w代表宽度方向的像素点个数,c代表颜色通道数。
计算机眼下图像

灰度图像

同样的,人眼看到的灰度图像是不同亮度的组合,而计算机看到的是单通道的亮度矩阵。对于灰度图也就是黑白图来说他只有一个颜色通道,图片的维度是二维的可以用【h,w】来表示,h代表高度方向的像素点个数,w代表宽度方向的像素点个数。

2.图像相关的基本函数

这里我们介绍使用python调用Opencv库中的基本图像处理函数的方法。

图像的读取函数

图像的读取函数:

import cv2
img =cv2.imread()

使用python直接调用OpenCV库后,使用imread()函数实现图像读取,功能是加载图像文件成为一个 Mat 对象,其中第一个参数表示图像文件名称,第二个参数表示加载的图像是什么类型,支持常见的三个参数值。读取的若为彩色图像则img为三维的矩阵,读取的若为灰度独享,img为二维矩阵。OpenCV 支持 JPG、PNG、TIFF 等常见格式图像文件加载(默认读取的格式是 BGR)。另外注意imread()函数的输入为图像的存放路径,当输入绝对路径时,例如输入路径’C:\Users\zhangyu\Pictures\Saved Pictures\1.png’会报错,这是因为读取文件时使用\。字符串中\是被当作转义字符来使用,经过转义之后可能就找不到文件的路径资源了。
推荐下面三种写法:

#显式声明字符串(加r):
img =cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\1.png')
#绝对路径写法:
img =cv2.imread('C:\\Users\\..\\Pictures\\Saved Pictures\\1.png')
#使用Linux的路径 /:
img =cv2.imread('C:/Users/../Pictures/Saved Pictures/1.png')

应用

图像的显示函数:

import cv2
 cv2.imshow(name, img)
 cv2.waitKey(time)
 cv2.destroyAllWindows()

其中imshow()函数的输入变量name为展示窗口的命名变量,img为前面读取的图像。waitKey()的输入变量time为窗口等待的时间值,单位为ms。默认值为0,即不写参数时默认值为0,代表无限等待,此时可以通过按任意键来终止图像窗口显示。当按上述命令显示图像时,显示粗昂口的大小是不可调节的,所以有时候在显示大矩阵图像时,如[h,w]=[2000,2000]时,可能只在屏幕上显示部分,其余部分显示不下的情况,此时我们可以使用OpenCV 的窗口调节函数namedWindow(),如下面例子所示:

import cv2
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\lena.jpg')
cv2.namedWindow("image", cv2.WINDOW_NORMAL)
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果:
在这里插入图片描述

图像的截取

Pyhon中提供直接的图像截取功能,截取前我们一般先通过shape函数使用方式如下所示:

import cv2
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\lena.jpg')
a,b,c = img.shape
trunc = img[50:180, 50:180]
cv2.namedWindow("image", cv2.WINDOW_NORMAL)
cv2.imshow('image', trunc)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出的截断后的图像为;
在这里插入图片描述

色彩通道的提取通过

OpenCV提供的的 split() 函数可以进行颜色的通道提取。使用方法如下:

import cv2
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\lena.jpg')
b,g,r = cv2.split(img)
print (r)

输出红色通道的数值矩阵为:
在这里插入图片描述

只保留B通道的图像

前面介绍过 OpenCV 默认读取的格式是 BGR,则只保留B通道(蓝色)的图像操作为:

import cv2
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\lena.jpg')
img[:,:,1] = 0
img[:,:,2] = 0
cv2.imshow('B', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出:
在这里插入图片描述

只保留G通道的图像

只保留G通道(绿色)的图像操作为:

import cv2
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\lena.jpg')
img[:,:,0] = 0
img[:,:,2] = 0
cv2.imshow('G', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出:
在这里插入图片描述

只保留R通道的图像

只保留G通道(红色)的图像操作为:

import cv2
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\lena.jpg')
img[:,:,0] = 0
img[:,:,1] = 0
cv2.imshow('G', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出为:
在这里插入图片描述

图像的扩充

OpenCV库提供copyMakeBorder()函数直接实现对图像的扩充功能,图像的扩充函数:

imgborder= cv.copyMakeBorder(img,top_size,bottom_size,left_size,right_size,borderType)

其输入的参数有六项,依次为待扩充原图像img,图像向上,下,左,右扩充的尺寸,top_size,bottom_size,left_size,right_size,以及向扩充的具体方式borderType。OpenCV库中提供了五种边界填充的方式,分别为

  1. BORDER_REPLICATE : 复制法,也就是复制最边缘像素。
  2. BORDER_REFLECT :反射法,对感兴趣的图像中的像素在两边进行复制。例如:fedcba|abcdefgh|hgfedcb
  3. BORDER_REFLECT_101 :反射法,也就是以最边缘像素为轴、对称复制。例如:gfedcb|abcdefgh|gfedcba
  4. BORDER_WRAP : 外包装法 cdeifgh|abcdefgh|abcdefg
  5. BORDER_CONSTANT : 常量法,常数值填充。

下例我们分别展示五种填充方式的效果。

import cv2
import matplotlib.pyplot as plt

top_size, buttom_size, left_size, right_size = (30, 30, 30, 30)
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\lena.jpg')
# 复制法,也就是复制最边缘像素
replicate = cv2.copyMakeBorder(img, top_size, buttom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)

# 反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb
reflect = cv2.copyMakeBorder(img, top_size, buttom_size, left_size, right_size, borderType=cv2.BORDER_REFLECT)

# 反射法,也就是以最边缘像素为轴、对称、gfedcb|abcdefgh|gfedcba
reflect01 = cv2.copyMakeBorder(img, top_size, buttom_size, left_size, right_size, borderType=cv2.BORDER_REFLECT_101)

# 外包装法 cdeifgh|abcdefgh|abcdefg
wrap = cv2.copyMakeBorder(img, top_size, buttom_size, left_size, right_size, borderType=cv2.BORDER_WRAP)

# 常量法,常数值填充
constant = cv2.copyMakeBorder(img, top_size, buttom_size, left_size, right_size, borderType=cv2.BORDER_CONSTANT)

plt.subplot(231)
plt.imshow(img, 'gray')
plt.title('ORIGINAL')

plt.subplot(232)
plt.imshow(replicate, 'gray')
plt.title("REPLICATE")

plt.subplot(233)
plt.imshow(reflect, 'gray')
plt.title("REFLECT")

plt.subplot(234)
plt.imshow(reflect01, 'gray')
plt.title("REPLICATE01")

plt.subplot(235)
plt.imshow(wrap, 'gray')
plt.title("WRAP")

plt.subplot(236)
plt.imshow(constant, 'gray')
plt.title("CONSTANT")
# 图像显示
plt.show()

图像的数值计算

在Python中可以直接对图像进行数值操作,

import cv2
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\lena.jpg')
img2 = img + 40
print(img)
print(img2)

img1的输出结果为(由于输出结果有点长,这里只截取部分结果):
在这里插入图片描述
img2的输出结果为(由于输出结果有点长,这里只截取部分结果):
在这里插入图片描述
这是通过对比img1与img2的结果可以发现,img2 中的每个值都加了 40 ,如果值超出 255,则得到结果如:224+ 40 = 264,264 - 255 = 9,那么计算结果就为 9-1=8(因为像素值从0开始显示)。
OpenCV库也中提供了图像数字运算的库函数add(),此时若两图像相加大于255,将会直接进行截断到255。如下例子所示:

import cv2
img = cv2.imread(r'C:\Users\..\Pictures\Saved Pictures\lena.jpg')
img2 = img+30;
result = cv2.add(img, img2)
print(result)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

加和图像的输出图像矩阵结果为:
在这里插入图片描述
可以发现超过255的数值直接被截断。
输出的加和的图像为:
在这里插入图片描述
与原图像相比我们发现图像整体更亮,这是由于更多的像素值趋近于255,在图像中表征为白色。

图像融合

我们需要融合的两张图像如下:

在这里插入图片描述在这里插入图片描述
我们首先试着直接将两张图像进行相加,如下所示

import cv2
img_rabbit = cv2.imread(r"C:\Users\..\Pictures\Saved Pictures/rabbit.jpg")
img_pig = cv2.imread(r"C:\Users\..\Pictures\Saved Pictures/pig.jpg")
result = img_rabbit + img_pig
print(result)

此时会报错:ValueError: operands could not be broadcast together with shapes (313,500,3) (750,1200,3) 。所以想进行图像相加,必须是两张具有相同矩阵维度的图像。对于两个矩阵维度不同的图像,我们可以先使用resize()函数是图像具有相同的维数,最后使用addWeighted()函数实现图像融合,操作如下:

import cv2
img_rabbit = cv2.imread(r"C:\Users\..\Pictures\Saved Pictures/rabbit.jpg")
img_pig = cv2.imread(r"C:\Users\..\Pictures\Saved Pictures/pig.jpg")
# img_pig设置与img_rabbit一样的数值
h, w, c = img_rabbit.shape
img_pig = cv2.resize(img_pig, (w, h))
result = cv2.addWeighted(img_pig, 0.4, img_rabbit, 0.6, 0)
print(result)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

融合后的图像结果为:
在这里插入图片描述

图像保存

图像的保存非常简单,只需要使用OpenCV库函数 imwrite() 方法即可将图像保存起来。 imwrite()有两个输入参数,第一个为要保存的路径,第二个为要保存的图像。这里我们将上面的融合图像保存:

import cv2
img_rabbit = cv2.imread(r"C:\Users\..\Pictures\Saved Pictures/rabbit.jpg")
img_pig = cv2.imread(r"C:\Users\..\Pictures\Saved Pictures/pig.jpg")
h, w, c = img_rabbit.shape
img_pig = cv2.resize(img_pig, (w, h))
result = cv2.addWeighted(img_pig, 0.4, img_rabbit, 0.6, 0)
#相对路径,保存在当前程序路径下
cv2.imwrite('./imgfusion.jpg', result)
#绝对路径,保存在电脑指定位置
cv2.imwrite(r'C:\Users\..\Pictures\Saved Pictures/imgfusion.jpg', result)

当前路径保存结果为:
在这里插入图片描述

3.视频的处理

最后这里我们将简单介绍一下视频的处理,视频就是一帧一帧的图像连续排在一起进行连续放映。OpenCV库函数VideoCapture() 可以捕获摄像头,用数字来控制不同的设备,也可以通过指定路径获取视频文件。下例中我们读取视频并将视频转化为灰度视频。

import cv2

video = cv2.VideoCapture("./.mp4")
# 检查是否打开正确
if video.isOpened():
    # open 得到的是一个布尔值,正常打开返回True否则返回False
    # frame 返回当前帧的图像
    open, frame = video.read()
else:
    open = False
    
while open:
    ret, frame = video.read()
    # 如果读到的帧数不为空,那么就继续读取,如果为空,就跳出循环
    if frame is None:
        break
    if ret == True:
        # 彩色图像转换为灰度图
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow("video",gray)
        # 这里使用 waitKey 可以控制视频的播放速度,数值越小,播放速度越快
        # 这里0xFF == 27为按下 ESC 键即可退出该窗口
        if cv2.waitKey(10) & 0xFF == 27:
            break
video.release()
cv2.destroyAllWindows()

运行该程序就会去读取当前路径下的 test.mp4 文件,将视频显示在名为 video 的窗口上,如下:
在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值