OpenCV的全称是:Open Source Computer Vision Library。OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
cv2是OpenCV库在Python中的接口
Win+R打开cmd:
pip install opencv-python
具体介绍:
1. 图像缩放
① 图像缩放:将图像大小调整为 (256, 256):
image = cv2.resize(image_src, (256,256))
cv2.resize(): 这是OpenCV库中用于调整图像大小的函数。
2. 中心裁剪
② 中心裁剪:计算正确的起始索引,裁剪出大小为 (224, 224) 的中心区域
startx=(256//2)-(224//2)
starty=(256//2)-(224//2)
image=image[starty:starty+224,startx:startx+224]
首先找到原始图像(256x256)的中心点坐标(即 (128, 128),因为 256 // 2 等于 128)。然后,它们计算从这个中心点出发,到裁剪区域(224x224)左上角点的偏移量。由于裁剪区域也是中心对齐的,因此这个偏移量就是裁剪区域的一半宽度(或高度)。 对于 224x224 的裁剪区域,(224 // 2) 等于 112。所以,从原始图像的中心点 (128, 128) 出发,向左和向上各偏移 112 个像素,就得到了裁剪区域的左上角坐标 (16, 16)
image=image[starty:starty+224,startx:startx+224]
裁剪了一个从(starty, startx)开始,宽度和高度都为224像素的区域。starty和startx是裁剪区域左上角的坐标,它们是通过计算原始图像中心点和裁剪区域宽度/高度的一半来确定的。
image[starty:starty+224, startx:startx+224]这部分代码首先指定了裁剪区域的起始行starty,然后指定了裁剪区域的结束行(即starty+224),同理也指定了裁剪区域的起始列startx和结束列(即startx+224)。
3. 标准化
③ 标准化:使用代码中设置的 _mean 和 _std 对图像像素进行标准化
image=(image-_mean)/_std
_mean 和 _std 通常是预定义的数值,分别代表图像数据集的平均值(mean)和标准差(standard deviation)。这些值通常是在整个训练集上计算得出的,并用于对图像进行标准化。
image-_mean:这部分代码从图像数据的每个像素值中减去平均值。这样做是为了将像素值移动到以0为中心的分布,这样可以使模型更容易学习。
(image-_mean)/_std:在减去平均值之后,再将结果除以标准差。这会将像素值缩放到一个更小的范围,通常是[-1, 1]或类似的范围(取决于_std的具体值)。这种缩放可以进一步简化模型的训练过程,因为它使梯度更新在参数空间中更加一致。
4. 代码解读
完整代码:
#task-start
import numpy as np
import pandas as pd
import json
import cv2
import os
def img_processor(data_path, dst_size = (224,224)):
Image_std = [0.229, 0.224, 0.225]
Image_mean = [0.485, 0.456, 0.406]
_std = np.array(Image_std).reshape((1,1,3))
_mean = np.array(Image_mean).reshape((1,1,3))
image_src = cv2.imread(data_path)
image=cv2.resize(image_src,(256,256))
startx=(256//2)-(224//2)
starty=(256//2)-(224//2)
image=image[starty:starty+224,startx:startx+224]
image=(image-_mean)/_std
return image_src, image, (startx,starty)
def simple_generator(data_list, json_file, dst_size = (224, 224)):
with open(json_file, 'r') as f:
data = json.load(f)
folder_map = {v[0]: (int(k), v[1]) for k,v in data.items()}
for img_path in data_list:
image_src, image, (startx,starty) = img_processor(img_path, dst_size)
label = folder_map[img_path.split('/')[-2]]
yield image_src, image, label, (startx,starty)
def main():
Image_path = 'Imagedata/images'
Json_path = 'Imagedata/image_class_index.json'
data_list = []
for dirname, _, filenames in os.walk(Image_path):
if os.path.basename(dirname).startswith('n'):
for filename in filenames:
data_list.append(os.path.join(dirname, filename))
# 创建生成器
generator = simple_generator(data_list, Json_path)
# 查看示例,检查图像、标签等属性的正确性
num_samples = 5
for _ in range(num_samples):
image_src, image, label, (startx,starty) = next(generator)
print("SrcImage shape:", image_src.shape)
print("Image shape:", image.shape)
print("Label:", label)
print("startx and starty:",(startx,starty))
if __name__ == '__main__':
main()
#task-end
具体解释:
data_list = []
for dirname, _, filenames in os.walk(Image_path):
if os.path.basename(dirname).startswith('n'):
for filename in filenames:
data_list.append(os.path.join(dirname, filename))
遍历一个图像文件夹(Image_path),收集以’n’开头的子文件夹中的图像文件路径,并准备使用一个名为simple_generator的生成器函数来生成图像、标签和其他信息
#创建生成器
generator = simple_generator(data_list, Json_path)
def simple_generator(data_list, json_file, dst_size = (224, 224)):
with open(json_file, 'r') as f:
data = json.load(f)
folder_map = {v[0]: (int(k), v[1]) for k,v in data.items()}
for img_path in data_list:
image_src, image, (startx,starty) = img_processor(img_path, dst_size)
label = folder_map[img_path.split('/')[-2]]
yield image_src, image, label, (startx,starty)
dst_size:目标图像大小,默认为 (224, 224)。
调用 img_processor 函数,传入图像路径 img_path 和目标大小 dst_size。使用 yield 关键字返回原始图像 image_src、经过处理的图像 image(已经缩放和归一化)以及一个起始坐标元组 (startx, starty)(在这个示例中,起始坐标被硬编码为 (0, 0),因为没有提供实际的边界框信息)
def img_processor(data_path, dst_size = (224,224)):
Image_std = [0.229, 0.224, 0.225]
Image_mean = [0.485, 0.456, 0.406]
_std = np.array(Image_std).reshape((1,1,3))
_mean = np.array(Image_mean).reshape((1,1,3))
image_src = cv2.imread(data_path)
定义了两个常量列表 Image_std 和 Image_mean,它们分别表示图像的标准差和均值。这些值通常用于对图像进行归一化,以便输入到神经网络模型中。
这些特定的数值([0.485, 0.456, 0.406] 和 [0.229, 0.224, 0.225])是在ImageNet数据集的数百万张图像上计算得到的统计值。由于ImageNet是一个非常大且多样化的数据集,因此这些统计值可以很好地代表一般自然图像的像素分布。因此,当使用预训练的ImageNet模型来处理新的图像数据时,通常也会使用这些相同的归一化参数。
5. 扩展
灰度化
在Python中,使用OpenCV库可以很方便地进行灰度化操作:
import cv2
#读取彩色图像
color_image = cv2.imread('image.jpg')
#将彩色图像转换为灰度图像
gray_image = cv2.cvtColor(color_image, cv2.COLOR_BGR2GRAY)
#显示或保存灰度图像
cv2.imshow('Gray Image', gray_image)
cv2.imwrite('gray_image.jpg', gray_image)
注意:在OpenCV中,图像默认是以BGR(蓝绿红)格式读取的,而不是RGB。因此,在转换为灰度图像时,应使用cv2.COLOR_BGR2GRAY而不是cv2.COLOR_RGB2GRAY。
图像旋转
import cv2
import numpy as np
# 读取图像
image = cv2.imread('your_image.jpg')
# 获取图像的高度和宽度
(h, w) = image.shape[:2]
# 设置旋转中心为图像中心
center = (w // 2, h // 2)
# 旋转角度,这里以45度为例
angle = 45
# 获取旋转矩阵(这里使用cv2.getRotationMatrix2D函数)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
# 进行旋转操作
rotated = cv2.warpAffine(image, M, (w, h))
# 显示旋转后的图像
cv2.imshow('Rotated Image', rotated)
首先读取了一张图像,并获取了它的高度和宽度。然后,设置了旋转中心为图像的中心,并指定了一个旋转角度(这里为45度)。接着,使用cv2.getRotationMatrix2D
函数获取了一个旋转矩阵,这个矩阵描述了如何将图像上的每个点从原始位置移动到新的位置。最后,使用cv2.warpAffine
函数进行了实际的旋转操作,并显示了旋转后的图像。