Python + OpenCV 日常小技巧与常见坑整理

· 约 3 分钟 更新于 2026-09-19 ·
本文目录(18 节)

读图失败、窗口不刷新、视频循环不退出,常常不是图像算法的问题,而是输入检查和事件处理漏了一步。这里先整理 OpenCV 的读取与显示流程,再解释数组形状、按键和字符串检查;遇到报错时可以按具体环节回查。

1. OpenCV 读取与显示图片的正确姿势

常见错误

不少初学者写 OpenCV 读取图片时常出现如下写法:

import cv2 as cv
cat = cv.imread('./images/1.jpg')
print(cat.shape)
cv.imshow('cat')
cv.waitKey(0)
cv.destroyAllWindows()

问题:

  • cv.imshow('cat') 参数不全,需给图片数组
  • 没有判断图片是否读取成功
  • 错误使用 .shape,未做 None 检查

推荐规范写法

import cv2 as cv
cat = cv.imread('./images/1.jpg')
if cat is None:
    print("图片读取失败,请检查路径!")
else:
    print(cat.shape)
    cv.imshow('cat', cat)
    cv.waitKey(0)
    cv.destroyAllWindows()

灰度图像读取与转换

两种灰度化方法:

img = cv.imread('./images/1.jpg', cv.IMREAD_GRAYSCALE)
# 或者
img = cv.imread('./images/1.jpg')
if img is None:
    raise FileNotFoundError('./images/1.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

2. OpenCV 读取和处理 HDR 图像

  • 读取 HDR 图片需要用 cv.IMREAD_UNCHANGED 保留高动态范围数据。
  • 若需可视化或保存,需做 Tonemap 或归一化。
import numpy as np
img_hdr = cv.imread('./images/1.hdr', cv.IMREAD_UNCHANGED)
if img_hdr is None:
    raise FileNotFoundError('./images/1.hdr')
if img_hdr.dtype != np.float32 or img_hdr.ndim != 3 or img_hdr.shape[2] != 3:
    raise ValueError('此 Tonemap 示例要求 float32 三通道 HDR 输入')
tonemap = cv.createTonemap(gamma=2.2)
ldr = tonemap.process(img_hdr)
ldr_8bit = (ldr * 255).clip(0, 255).astype('uint8')
cv.imshow('LDR', ldr_8bit)
cv.waitKey(0)
cv.destroyAllWindows()

3. 随机生成图像与 reshape/resize 区别

随机生成一张彩色/灰度/HDR图像

import numpy as np
import cv2 as cv
img = np.random.randint(0, 256, (480, 640, 3), dtype=np.uint8)  # 彩色
cv.imshow('random', img)
cv.waitKey(0)
cv.destroyAllWindows()

reshape 与 resize 的区别

  • reshape 保留元素数量,但重新解释空间与通道布局,显示内容可能明显改变;它不做缩放插值,也不保证总是零拷贝。
  • resize 用于实际缩放图片(等比例缩放、指定尺寸)。
# 正确缩放
img_resize = cv.resize(img, (100, 100))

4. OpenCV 视频流读取、按键控制及常见陷阱

视频读取正确写法

import cv2 as cv
cap = cv.VideoCapture(0)
try:
    if not cap.isOpened():
        raise RuntimeError('无法打开摄像头,请检查权限和设备编号')
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        cv.imshow('ad', frame)
        if cv.waitKey(1) & 0xFF == ord('q'):
            break
finally:
    cap.release()
    cv.destroyAllWindows()

按键检测与 0xFF 的作用

if cv.waitKey(40) & 0xFF == ord('q'):
    break
  • 0xFF 保留低 8 位,常用于比较普通字符键;它不保证所有平台、键盘布局都返回相同编码。
  • ord('q') 为ASCII码值。
  • 这样写能避免高字节导致按键判断失效的兼容性问题。

按键原理说明

  • 未按键时 waitKey 返回 -1;需要完整特殊键码时使用 waitKeyEx,并检查当前 GUI 后端的行为。
  • 标准按键(a-z, 0-9)一般没问题,特殊键(方向键、功能键)编码更高。

5. Python 字符串常用校验方法和 any 手撕原理

常用字符串校验

s = input()
print(any(c.isalnum() for c in s))
print(any(c.isalpha() for c in s))
print(any(c.isdigit() for c in s))
print(any(c.islower() for c in s))
print(any(c.isupper() for c in s))

any() 本质与手写实现

def my_any(iterable):
    for x in iterable:
        if x:
            return True
    return False

6. 颜色代码入门

  • #000000 —— 纯黑色 (RGB(0,0,0))
  • #FFFFFF —— 纯白色 (RGB(255,255,255))

7. 常见代码风格建议

  • 运算符两侧要加空格(PEP8规范)。
  • 变量命名要避免覆盖模块名(如 cap 不要既是模块名又是变量名)。

总结

今天主要复习了 OpenCV 读图/写图/视频流的各种易错点与底层原理,练习了字符串判断相关的 Python 小技巧,并对按键检测、十六进制、位运算等知识点做了拓展。 图像处理脚本与窗口、摄像头测试要分开验收:本轮检查了代码中的输入保护、模块别名和资源释放,但未连接摄像头,也未运行 HDR 与 GUI 示例。无桌面的服务器应保存结果文件,不应把窗口无法打开误判成算法失败。


欢迎大家留言讨论,共同进步!


💬 评论

这套方案在哪一步卡住了?也欢迎补充你的实现方式或踩坑经验。

正在连接评论服务,首次访问可能需要几秒…