👈👈👈 欢迎点赞收藏关注哟 👍👍👍
👉👉👉 快进来看爆款文章 🔥🔥🔥
一. 前言
上一篇我们了解了 计算机视觉的基础概念 , 那么这一篇就继续来深入应用 :
对于普通的开发者来说 ,特征工程 ,算法变换这些还太远。就应用角度来说 ,多数只是调用工具实现需求 ,而工具这一块最有名的无非就是 OpenCV 了。
通常一个简单的图形读取分为几步?
二. 基础入门
2.1 OpenCV 读取图像
- 语法 :
retval = cv2.imread( filename[, flags] )
- retval : 未读取到图像是 None
- flags : 读取标记 , 支持
正常,灰度,BGR 图像
# 读取彩色图像(默认方式)
image = cv2.imread(image_path)
# 读取灰度图像
gray_image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
# 读取图像时保持 alpha 通道
alpha_image = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)
2.2 OpenCV 显示图像
- 语法 :
cv2.imshow( winname, mat )
- winname : 窗口名称
- mat : 要显示的图像
// 显示图像
cv2.imshow('Image', image)
关联附加操作 :等待按键确定
当用户按下按键后,该语句会被执行,并获取返回值 。 如果在上述代码中不使用该代码 ,则图片显示会瞬间完成。
通过该代码可以实现暂停功能
- 语法 : retval = cv2.waitKey( [delay] )
- delay : 等待时间 。 默认为0 ,可以为正数
// 持续暂停等待按键确认
// - 无限期等待键盘事件。当任何键被按下时,程序继续执行
cv2.imshow('Image', image)
cv2.waitKey(0)
// - 等待 n 毫秒的键盘事件
// - 如果在指定时间内有键按下,程序继续执行并返回按键的 ASCII 码
// - 如果没有键按下,返回 -1
cv2.waitKey(3000)
// 通常可以返回处理的按键 :
if key == ord('q'):
print("按下了 'q' 键")
elif key == ord('s'):
cv2.imwrite('saved_image.jpg', image)
print("按下了 's' 键,图像已保存为 'saved_image.jpg'。")
关联操作 : 关闭窗口
cv2.destroyAllWindows( )
2.3 保存图像
- 语法 : retval = cv2.imwrite( filename, img[, params] )
- filename : 保存的完整路径名
- img : 被保存的图像
- param : 可选参数 ,支持
- cv2.IMWRITE_JPEG_QUALITY: 指定图片质量 (JPG)
- cv2.IMWRITE_PNG_COMPRESSION : 指定压缩级别(PNG)
// 正常保存
cv2.imwrite('output_image.jpg', image)
// 图像质量,值范围从 0 到 100(默认值为 95)
cv2.imwrite('output_image.jpg', image, [cv2.IMWRITE_JPEG_QUALITY, 90])
// 压缩级别,值范围从 0 到 9(默认值为 3)
cv2.imwrite('output_image.png', image, [cv2.IMWRITE_PNG_COMPRESSION, 5])
2.4 其他的图像基本操作
尺寸操作
// 获取图像的宽高并且打印
height, width = image.shape[:2]
print(f'{height} x {width}')
// 调整尺寸
resized_image = cv2.resize(image, (width, height))
# 按照比例缩放图片
resized_image = cv2.resize(image, None, fx=0.5, fy=0.5)
# 按照比例扩展图片
resized_image = cv2.resize(image, None, fx=2.5, fy=2.5)
# 按照尺寸调整图片
scale_factor = 30 # 放大倍数
new_height = height * scale_factor
new_width = width * scale_factor
resized_image = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_NEAREST)
## interpolation:插值方法,用于重采样图像。常见的插值方法包括:
cv2.INTER_NEAREST:最近邻插值
cv2.INTER_LINEAR:双线性插值(默认值)
cv2.INTER_AREA:使用像素区域关系进行重采样。对于缩小图像非常有效
cv2.INTER_CUBIC:4x4 像素邻域的双三次插值
cv2.INTER_LANCZOS4:8x8 像素邻域的 Lanczos 插值
旋转操作
# 图像旋转
center = (width / 2, height / 2)
M = cv2.getRotationMatrix2D(center, 45, 1.0)
new_image = cv2.warpAffine(image, M, (width, height))
# getRotationMatrix2D : 用于生成二维旋转矩阵
cv2.getRotationMatrix2D(center, angle, scale)
- center:旋转中心点,格式为 (x, y)
- angle:逆时针旋转角度,以度为单位
- scale:缩放因子
# warpAffine : 用于对图像进行仿射变换
cv2.warpAffine(src, M, dsize, dst=None, flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=0)
- src:输入图像
- M:变换矩阵,通常由 cv2.getRotationMatrix2D 生成
- dsize:输出图像的大小,格式为 (width, height)
- dst:输出图像。这个参数通常省略,直接接收返回值
- flags:插值方法。常用的有 cv2.INTER_LINEAR、cv2.INTER_NEAREST 等
- borderMode:边界像素模式,默认值为 cv2.BORDER_CONSTANT
- borderValue:边界像素填充值,当 borderMode 为 cv2.BORDER_CONSTANT 时有效
翻转操作
# 垂直翻转
flipped_image = cv2.flip(image, 0)
# 水平翻转
flipped_image = cv2.flip(image, 1)
# 同时进行垂直和水平翻转
flipped_image = cv2.flip(image, -1)
当然除了这些常见的操作 ,还有一些高级操作,例如模糊锐化这种,我们在后续高阶用法中综合展示!!
三. 高阶用法
3.1 像素处理
像素处理在上一篇也简单聊过 ,这里就再深入一下 :
就像上文 基础概念 里面讲的一样,图像是由一个个像素点组成的 ,最常见的像素操作分为以下几类 :
3.1.1 像素的定位和索引
- 这个阶段就需要引入 numpy 来进行一些数组的操作了 ,第一步为每个图像像素点生成一个二维数组
import cv2
import numpy as np
# 读取图像
image_path = "C:\\Users\\Desktop\\test.png"
image = cv2.imread(image_path)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 获取灰度值
height, width = gray_image.shape
scale_factor = 100 # 放大倍数
new_height = height * scale_factor
new_width = width * scale_factor
# 放大图像
resized_image = cv2.resize(gray_image, (new_width, new_height), interpolation=cv2.INTER_NEAREST)
# 在放大后的图像上标注像素点
for i in range(height):
for j in range(width):
gray_value = gray_image[i, j]
text = f'({i},{j})'
# 在放大后的像素区域的中心位置绘制像素值
x = j * scale_factor + scale_factor // 4
y = i * scale_factor + scale_factor // 2
inverted_color = 255 - int(gray_value)
cv2.putText(resized_image, text, (x, y), cv2.FONT_HERSHEY_SIMPLEX, 0.3, inverted_color, 1, cv2.LINE_AA)
# 显示新图像
cv2.imshow("Gray Image with Values", resized_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存新图像
cv2.imwrite("test001.png", resized_image)
- 该段代码还可以用于展示灰度值 / RGB 值等多项操作
- 当我们了解到这些值后 ,就可以对数据进行筛选和处理了
3.1.2 像素区域的查询及操作
查询的目的是为了我们把想要的像素点筛选出来 ,通过各种算法的手法对像素点进行处理 :
案例一 : 切换图片底色
import cv2
import numpy as np
# 读取图像
image = cv2.imread(image_path)
# 检查图像是否成功读取
if image is None:
print("图像读取失败,请检查文件路径。")
else:
# 定义白色的阈值
lower_white = np.array([200, 200, 200], dtype=np.uint8)
upper_white = np.array([255, 255, 255], dtype=np.uint8)
# 创建掩膜,找到白色部分
mask = cv2.inRange(image, lower_white, upper_white)
# 将白色部分替换为灰色
image[mask == 255] = [128, 128, 128]
# 显示处理后的图像
cv2.imshow('Processed Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存处理后的图像
cv2.imwrite('processed_image.jpg', image)
这里说白了就是对不同像素点的操作 ,提高像素点的颜色范围
案例二 : 裁剪特定颜色图片
import cv2
import numpy as np
def remove_red_area(image_path):
# 读取图像
image = cv2.imread(image_path)
# 将图像从 BGR 转换为 HSV
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 定义红色的 HSV 范围
lower_red1 = np.array([0, 70, 50])
upper_red1 = np.array([10, 255, 255])
lower_red2 = np.array([170, 70, 50])
upper_red2 = np.array([180, 255, 255])
# 创建红色掩码
mask1 = cv2.inRange(hsv_image, lower_red1, upper_red1)
mask2 = cv2.inRange(hsv_image, lower_red2, upper_red2)
red_mask = cv2.bitwise_or(mask1, mask2)
# 将红色区域变为白色
image[red_mask != 0] = [255, 255, 255]
# 显示结果
cv2.imshow('Image with Red Area Removed', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存结果
cv2.imwrite('image_without_red.jpg', image)
return image
# 使用函数移除红色区域
image_path = "C:\\Users\\Desktop\\test.png"
remove_red_area(image_path)
本质上还是进行了搜索和替换。
3.2 美化处理
美颜处理本质上是对整体图片色调的处理,高级的学不来 ,只能玩点简单的
,常见的有以下几种 :
- 线性变换:通过对图像像素值进行线性变换来调整对比度和亮度。
- 直方图均衡化:通过调整图像的直方图来增强对比度。
import cv2
import numpy as np
def adjust_contrast(image_path, alpha, beta):
# 读取图像
image = cv2.imread(image_path)
# 调整对比度和亮度
adjusted_image = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
# 显示结果
cv2.imshow('Original Image', image)
cv2.imshow('Adjusted Image', adjusted_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 保存结果
cv2.imwrite('adjusted_image.jpg', adjusted_image)
return adjusted_image
# 使用函数调整对比度(例如:对比度增加1.5倍,亮度增加50)
adjust_contrast('path/to/your/image.jpg', alpha=1.5, beta=50)
更高级的操作这里就不尝试了 ,后续单章深入了解下。
3.3 水印处理
import cv2
import os
import numpy as np
# 对图像进行旋转
def create_rotated_text_image(text, font, font_scale, thickness, color, angle):
# 获取文本尺寸和基线
# font_scale :字体比例因子
# thickness : 文本线条的粗细(以像素为单位)
(text_w, text_h), baseline = cv2.getTextSize(text, font, font_scale, thickness)
# 创建一个包含文本的透明图像
text_img = np.zeros((text_h + baseline, text_w, 4), dtype='uint8')
cv2.putText(text_img, text, (0, text_h), font, font_scale, color + (255,), thickness, cv2.LINE_AA)
# 计算旋转矩阵
center = (text_w // 2, text_h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1)
# 旋转文字图像
rotated = cv2.warpAffine(text_img, M, (text_w, text_h + baseline), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=(0,0,0,0))
return rotated
# 为图像添加水印
def add_watermark(image, text, font=cv2.FONT_HERSHEY_SIMPLEX, font_scale=1, thickness=2, color=(255, 255, 255), alpha=0.5, angle=45, spacing=100):
# 获取图像尺寸
h, w = image.shape[:2]
# 创建一个透明背景
overlay = np.zeros((h, w, 4), dtype='uint8')
# 创建旋转的文字图像
rotated_text_img = create_rotated_text_image(text, font, font_scale, thickness, color, angle)
rotated_h, rotated_w = rotated_text_img.shape[:2]
# 在透明背景上绘制倾斜的文字
for y in range(0, h, rotated_h + spacing):
for x in range(0, w, rotated_w + spacing):
# 确保水印位置不会超出图像边界
if y + rotated_h <= h and x + rotated_w <= w:
overlay[y:y+rotated_h, x:x+rotated_w] = rotated_text_img
# 将透明背景与原始图像合并
image_bgra = cv2.cvtColor(image, cv2.COLOR_BGR2BGRA)
# 用于图像加权融合的函数。它可以将两张图像按指定的权重进行融合,从而实现图像混合、叠加
# alpha : 透明度
cv2.addWeighted(overlay, alpha, image_bgra, 1 - alpha, 0, image_bgra)
# 转回 BGR
image_result = cv2.cvtColor(image_bgra, cv2.COLOR_BGRA2BGR)
return image_result
# 读取图片
image_path = "C:\\Users\\Desktop\\test003.png"
# 检查文件是否存在
if not os.path.isfile(image_path):
print("错误:图像文件未找到!")
exit()
image = cv2.imread(image_path)
# 添加水印
watermarked_image = add_watermark(image, 'AntBlack', font_scale=2, thickness=1, color=(255, 255, 255), alpha=0.3, angle=20, spacing=200)
cv2.imshow("Gray Image with Values", watermarked_image)
cv2.waitKey(0)
这其中用到了以下几个函数 :
S1 : 获取一个水印图像
首先要拿到这个水印的长宽高及偏移 ,然后基于这些信息生成一个透明图像 ,并且把水印文字放在图像中
# 获取给定文本字符串在特定字体和比例下的尺寸的函数。该函数返回文本的宽度、高度和基线偏移量
(text_w, text_h), baseline = cv2.getTextSize(text, font, font_scale, thickness)
- text:要绘制的文本字符串。
- fontFace:字体类型
- fontScale:字体比例因子。
- thickness:文本线条的粗细(以像素为单位
# 返回值 :
- size:包含文本宽度和高度的元组 (width, height)。
- baseline:基线的偏移量(即从文本的底部到基线的距离)
# 创建一个透明的图像 , 通过 putText 为其赋值
text_img = np.zeros((text_h + baseline, text_w, 4), dtype='uint8')
cv2.putText(text_img, text, (0, text_h), font, font_scale, color + (255,), thickness, cv2.LINE_AA)
- dtype='uint8' 指定数组元素的数据类型为无符号8位整数 ,基于颜色通道 ,这里就会生成透明图像
S2 : 进行图像的整合
// 这个函数通过加权的方式将两张图像进行线性混合,可以用来实现图像叠加、融合效果等
cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) -> dst
- src1:第一张输入图像
- alpha:第一张图像的权重系数
- src2:第二张输入图像
- beta:第二张图像的权重系数
- gamma:加到加权和上的标量值(通常为0)
- dst:输出图像(可选)
- dtype:输出图像的类型(可选)
3.4 文字识别
之前这篇文章写过一部分 ,这里就不详细说了,主要是基于 tesseract , 对 OpenCV 的使用反而不多
总结
主要是一些基础的应用 ,从这些案例上 ,还可以继续深入 ,涉及其他的场景。
参考文档 :
- 计算机视觉40例 : 从入门到深度学习
- ChatGPT