《LearnPython-Python学习笔记》-关于OpenCV的坑

admin 2025-11-07 01:09:39 编程 来源:ZONE.CI 全球网 0 阅读模式
  • 3. 图片转BGR
  • 4. resize问题

    关于OpenCV的坑

    1. 无法修改摄像头参数
    2. 中文无法识别2.1 窗口中文标题无法识别2.1 中文路径无法识别
    3. 图片转BGR
    4. resize问题

    5. 无法修改摄像头参数原因1:摄像头不支持此参数比如:摄像头的帧率最高是30,但是你的电脑CPU带不动它,所以它在你电脑上的帧率只能达到22。

    原因2:opencv的问题我查到一个说法是opencv的权限比驱动低,所以无法修改,可以通过卸载摄像头驱动来修复,这个方法没有测试,看着就不靠谱。

    因此就是opencv的问题了。下面这个代码是广泛流传的打开摄像头代码,

    1. import numpy as np
    2. import cv2
    3. cap = cv2.VideoCapture(0) # 打开摄像头
    4. while(True):
    5. ret, frame = cap.read() # 读取图片
    6. cv2.imshow('frame',frame)
    7. # 退出
    8. if cv2.waitKey(1) & 0xFF == ord('q'):
    9. break
    10. cap.release()
    11. cv2.destroyAllWindows()

    代码是不存在问题,但是打开摄像头之后无法修改修改相机的参数,比如分辨率、帧率、亮度。

    1. cap = cv2.VideoCapture(camera_number + cv2.CAP_DSHOW)

    camera_number就是摄像头在你电脑上的设备号,0,1,2,…CAP_DSHOW是opencv初始化的一个参数,我找到一个参数列表,适用参数应该与相机的驱动有关系,而我使用的笔记本的摄像头(USB相机),因此使用CAP_DSHOW就行了。

    1. CAP_ANY = 0 # Auto detect
    2. CAP_VFW = 200 # Video For Windows (obsolete, removed)
    3. CAP_V4L = 200 # V4L/V4L2 capturing support
    4. CAP_V4L2 = CAP_V4L # Same as CAP_V4L
    5. CAP_FIREWIRE = 300 # IEEE 1394 drivers
    6. CAP_FIREWARE = CAP_FIREWIRE # Same value as CAP_FIREWIRE
    7. CAP_IEEE1394 = CAP_FIREWIRE # Same value as CAP_FIREWIRE
    8. CAP_DC1394 = CAP_FIREWIRE # Same value as CAP_FIREWIRE
    9. CAP_CMU1394 = CAP_FIREWIRE # Same value as CAP_FIREWIRE
    10. CAP_QT = 500 # QuickTime (obsolete, removed)
    11. CAP_UNICAP = 600 # Unicap drivers (obsolete, removed)
    12. CAP_DSHOW = 700 # DirectShow (via videoInput)
    13. CAP_PVAPI = 800 # PvAPI, Prosilica GigE SDK
    14. CAP_OPENNI = 900 # OpenNI (for Kinect)
    15. CAP_OPENNI_ASUS = 910 # OpenNI (for Asus Xtion)
    16. CAP_ANDROID = 1000 # Android - not used
    17. CAP_XIAPI = 1100 # XIMEA Camera API
    18. CAP_AVFOUNDATION = 1200 # AVFoundation framework for iOS (OS X Lion will have the same API)
    19. CAP_GIGANETIX = 1300 # Smartek Giganetix GigEVisionSDK
    20. CAP_MSMF = 1400 # Microsoft Media Foundation (via videoInput)
    21. CAP_WINRT = 1410 # Microsoft Windows Runtime using Media Foundation
    22. CAP_INTELPERC = 1500 # RealSense (former Intel Perceptual Computing SDK)
    23. CAP_REALSENSE = 1500 # Synonym for CAP_INTELPERC
    24. CAP_OPENNI2 = 1600 # OpenNI2 (for Kinect)
    25. CAP_OPENNI2_ASUS = 1610 # OpenNI2 (for Asus Xtion and Occipital Structure sensors)
    26. CAP_GPHOTO2 = 1700 # gPhoto2 connection
    27. CAP_GSTREAMER = 1800 # GStreamer
    28. CAP_FFMPEG = 1900 # Open and record video file or stream using the FFMPEG library
    29. CAP_IMAGES = 2000 # OpenCV Image Sequence (e.g. img_%02d.jpg)
    30. CAP_ARAVIS = 2100 # Aravis SDK
    31. CAP_OPENCV_MJPEG = 2200 # Built-in OpenCV MotionJPEG codec
    32. CAP_INTEL_MFX = 2300 # Intel MediaSDK
    33. CAP_XINE = 2400 # XINE engine (Linux)

    这是我写的一个完整Demo

    1. import cv2
    2. import os
    3. # Width, Height
    4. Camera_PROP_640x480 = (640, 480)
    5. Camera_PROP_800x600 = (800, 600)
    6. Camera_PROP_960_640 = (960, 640)
    7. Camera_PROP_1024x540 = (1024, 540)
    8. Camera_PROP_1024x600 = (1024, 600)
    9. Camera_PROP_1024x768 = (1024, 768)
    10. Camera_PROP_1080x960 = (1080, 960)
    11. Camera_PROP_1152x864 = (1152, 864)
    12. Camera_PROP_1280x600 = (1280, 600)
    13. Camera_PROP_1280x720 = (1280, 720)
    14. Camera_PROP_1280x768 = (1280, 768)
    15. Camera_PROP_1280x800 = (1280, 800)
    16. Camera_PROP_1280x960 = (1280, 960)
    17. Camera_PROP_1280x1024 = (1280, 1024)
    18. Camera_PROP_1360x768 = (1360, 768)
    19. Camera_PROP_1366x768 = (1366, 768)
    20. Camera_PROP_1400x1050 = (1400, 1050)
    21. Camera_PROP_1440x900 = (1440, 900)
    22. Camera_PROP_1600x900 = (1600, 900)
    23. Camera_PROP_1680x1050 = (1680, 1050)
    24. Camera_PROP_1920x1080 = (1920, 1080)
    25. Camera_PROP_2048x1080 = (2048, 1080)
    26. Camera_PROP_4096x2160 = (4096, 2160)
    27. Camera_PROP_Max = (300000, 300000)
    28. # 解决显示图片过大导致图片跑到显示器外边
    29. def imshow(winname, mat):
    30. ratio = mat.shape[0] // 600
    31. if ratio <= 1:
    32. ratio = 1.5
    33. cv2.namedWindow(winname, cv2.WINDOW_NORMAL)
    34. cv2.resizeWindow(winname, int(mat.shape[1] / ratio), int(mat.shape[0] / ratio))
    35. cv2.imshow(winname, mat)
    36. if __name__ == '__main__':
    37. print("=============================================")
    38. print("= 热键(请在摄像头的窗口使用) =")
    39. print("= w: 拍摄图片 =")
    40. print("= q: 退出 =")
    41. print("=============================================")
    42. # 新建文件夹 test
    43. class_name = 'test'
    44. if not os.path.exists(class_name):
    45. os.mkdir(class_name)
    46. index = 1
    47. # 打开相机
    48. cap = cv2.VideoCapture(0 + cv2.CAP_DSHOW)
    49. # fps = cap.get(cv2.CAP_PROP_FPS)
    50. # 设置相机亮度
    51. cap.set(cv2.CAP_PROP_BRIGHTNESS, 150)
    52. print(cap.get(cv2.CAP_PROP_BRIGHTNESS))
    53. # 设置相机增益
    54. cap.set(cv2.CAP_PROP_GAIN, 1)
    55. print(cap.get(cv2.CAP_PROP_GAIN))
    56. # 设置相机分辨率
    57. width, height = Camera_PROP_1280x720
    58. cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
    59. cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
    60. width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    61. height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    62. # 初始化opencv显示窗口‘capture’
    63. cv2.namedWindow('capture', cv2.WINDOW_NORMAL)
    64. cv2.resizeWindow('capture', width // 2, height // 2)
    65. # 设置相机帧率
    66. cap.set(cv2.CAP_PROP_FPS, 30)
    67. print(cap.get(cv2.CAP_PROP_FPS))
    68. # 新建一个'test.avi'文件
    69. fps = 8
    70. fourcc = cv2.VideoWriter_fourcc(*'XVID')
    71. out = cv2.VideoWriter('test.avi', fourcc, fps, (width, height))
    72. # 将相机录制到'test.avi'文件中
    73. while (int(cv2.getWindowProperty('capture', 0)) != -1):
    74. ret, frame = cap.read() # 获取当前帧
    75. if not ret:
    76. continue
    77. frame = cv2.flip(frame, 1, dst=None) # 镜像
    78. out.write(frame) # 写入帧
    79. imshow("capture", frame) # 显示
    80. # 判断相机退出
    81. input = cv2.waitKey(1) & 0xFF
    82. if input == ord('w'):
    83. cv2.imwrite("%s/%d.png" % (class_name, index), frame)
    84. print("%s: %d 张图片" % (class_name, index))
    85. index += 1
    86. elif input == ord('q'):
    87. break
    88. # 释放内存
    89. out.release()
    90. cap.release()
    91. cv2.destroyAllWindows()
    1. 中文无法识别OpenCV的中文乱码问题暂时还无法解决,可以把系统编码修改为UTF8格式来解决这个问题,但是这个方法的代价可能太高了,因此只能使用一些“曲线救国”的办法。

    2.1 窗口中文标题无法识别方法一:改用C++的OpenCV方法二:改用Python2版本,字符串变为 u’中文’还是不建议使用中文标题

    2.1 中文路径无法识别

    1. import cv2
    2. file_name = '测试/测试.bmp'
    3. img = cv2.imread(file_name)
    4. cv2.imshow('测试',img)
    5. cv2.waitKey()

    报错:

    1. cv2.error: OpenCV(4.1.1) C:\projects\opencv-python\opencv\modules\highgui\src\window.cpp:352: error: (-215:Assertion failed) size.width>0 && size.height>0 in function 'cv::imshow'

    方法一:用np.fromfile读取,OpenCV再从内存中读取图片

    1. import cv2
    2. import numpy as np
    3. file_name = '测试/测试.bmp'
    4. img = cv2.imdecode(np.fromfile(file_name, dtype=np.uint8), -1)
    5. cv2.imshow('test',img)
    6. cv2.waitKey()
    7. # 中文路径保存
    8. cv2.imencode('.bmp', img)[1].tofile('测试/测试2.bmp')

    方法二:使用其他库读取图片,然后转成numpy格式再转成OpenCV格式,注意OpenCV是BGR

    1. import cv2
    2. import numpy as np
    3. from PIL import Image
    4. Image.MAX_IMAGE_PIXELS = 1000000000 # 图片最大内存
    5. file_name = '测试/测试.bmp'
    6. img_plt = Image.open(file_name)
    7. # pillow转cv
    8. img_cv = cv2.cvtColor(np.asarray(img_plt), cv2.COLOR_RGB2BGR)
    9. # cv转pillow
    10. img_plt = Image.fromarray(cv2.cvtColor(img_cv, cv2.COLOR_BGR2RGB))
    11. cv2.imshow('test', img_cv)
    12. cv2.waitKey()

    方法三:这个方法跟上一个方法类似,但是我觉得比较有意思,是使用urllib通过url来获取图片,接着转成numpy格式再转为OpenCV格式

    1. import cv2
    2. import numpy as np
    3. from urllib.request import urlopen,pathname2url
    4. file_name = '测试/测试.bmp'
    5. file_url = 'file:' + pathname2url(file_name)
    6. img_url = urlopen(file_url)
    7. img_np = np.asarray(bytearray(img_url.read()), dtype="uint8")
    8. img_cv = cv2.imdecode(img_np, cv2.IMREAD_COLOR)
    9. cv2.imshow('test', img_cv)
    10. cv2.waitKey()

    3. 图片转BGR

    opencv貌似除了cv2.imread(file_name, 0)外,没有自动匹配位深度转灰度,因此在将图片转灰度需要考虑位深度,否则会报错

    1. def convert_BGR(image):
    2. """
    3. 转BGR
    4. :param image:原图像
    5. """
    6. if len(image.shape) == 2:
    7. image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
    8. elif len(image.shape) == 3:
    9. if image.shape[2] == 3:
    10. return image
    11. elif image.shape[2] == 4:
    12. image = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR)
    13. else:
    14. assert 'image channel too many'
    15. else:
    16. assert 'image channel too many'
    17. return image

    4. resize问题

    获取图片尺寸用img.shape(),会得到(高,宽,通道数),单通道图片是(高,宽)但是得到的resize图片的顺序是(宽,高)

    1. img = cv2.resize(img, (width,height))

    如果修改图片尺寸,用OpenCV的imshow显示正常,但是传到其他控件考虑会产生裂图(图片显示不正常)这是因为OpenCV的显示使用了优化,而其他控件打开图片是遵守width,height满足4的倍数比如PyQt的Qlabel控件显示图片需要将OpenCV的图片转换成QImage,不仅仅是传图片,还要对图片的尺寸进行调整,代码如下:

    1. showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], show.shape[1] * show.shape[2], QtGui.QImage.Format_RGB888)

    refhttps://blog.csdn.net/sinat_41657218/article/details/119301570

    以太坊cppgolang区别 编程

    以太坊cppgolang区别

    以太坊是一种去中心化的开源平台,它采用智能合约技术,旨在构建和运行不受干扰的分布式应用程序。作为目前最受欢迎的区块链平台之一,以太坊提供了多种编程语言的支持,其
    progolang 编程

    progolang

    Go语言(Golang)是由Google开发的一门静态类型编程语言。作为一名专业的Golang开发者,我深知这门语言的优势和特点。在本文中,我将介绍Golang
    golangn个发送者 编程

    golangn个发送者

    Golang是一种开源的编程语言,由Google团队开发,旨在提高程序的并发性和简化软件开发过程。在Go语言中,有时需要向多个接收者发送信息。本文将介绍如何在G
    golang技能图谱 编程

    golang技能图谱

    从互联网行业的快速发展到人工智能技术的日益成熟,各种编程语言也应运而生。而在这众多的编程语言中,Golang(即Go)作为一门强大且高效的开发语言备受关注。Go
    评论:0   参与:  5