学不会C的苦命人 发表于 2023-5-30 15:12:12

如何用python opencv调用摄像头拍照的同时读取这张照片

我最近在弄一个结课作业,关于图像识别的,现在的问题是我可以用python调用摄像头拍照但不能同时读取这张照片,各位大佬有什么代码能帮帮我吗{:10_266:}
我的调用摄像头的代码如下
import cv2

def video_demo():
    print('开始')
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)# 电脑自身摄像头
    i = 0# 定时装置初始值
    photoname = 1# 文件名序号初始值

    while True:
      i = i + 1
      reg, frame = cap.read()
      frame = cv2.flip(frame, 1)# 图片左右调换
      cv2.imshow('window', frame)

      if i == 50:# 定时装置,定时截屏,可以修改。
            filename = str(photoname) + '.png'# filename为图像名字,将photoname作为编号命名保存的截图
            cv2.imwrite('E:/asdfghj' + '\\' + filename, frame)# 截图 前面为放在桌面的路径 frame为此时的图像
            print(filename + '保存成功')# 打印保存成功
            i = 0# 清零

            photoname = photoname + 1
            if photoname >= 2:# 最多截图20张 然后退出(如果调用photoname = 1 不用break为不断覆盖图片)
                # photoname = 1
                break
      if cv2.waitKey(1) & 0xff == ord('q'):
            break
    # 释放资源
    cap.release()

video_demo()
cv2.destroyAllWindows()
我个人对python没什么太多了解,我一开始的代码是这样的
import cv2

def video_demo():
    print('开始')
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)# 电脑自身摄像头
    i = 0# 定时装置初始值
    photoname = 1# 文件名序号初始值

    while True:
      i = i + 1
      reg, frame = cap.read()
      frame = cv2.flip(frame, 1)# 图片左右调换
      cv2.imshow('window', frame)

      if i == 50:# 定时装置,定时截屏,可以修改。
            filename = str(photoname) + '.png'# filename为图像名字,将photoname作为编号命名保存的截图
            cv2.imwrite('E:/asdfghj' + '\\' + filename, frame)# 截图 前面为放在桌面的路径 frame为此时的图像
            print(filename + '保存成功')# 打印保存成功
            i = 0# 清零

            photoname = photoname + 1
            if photoname >= 2:# 最多截图20张 然后退出(如果调用photoname = 1 不用break为不断覆盖图片)
                # photoname = 1
                break
      if cv2.waitKey(1) & 0xff == ord('q'):
            break
    # 释放资源
    cap.release()
img = cv2.imread('E:/asdfghj/1.png',cv2.IMREAD_GRAYSCALE);
video_demo()
cv2.destroyAllWindows()

运行结果是这样的,那行读取图片的代码没起作用也没报错,想看看各位大佬有什么办法。

E:\Python\Python安装地点\python.exe D:\pythonProject\tuxiangduqushiyantwo\main.py
开始
1.png保存成功

进程已结束,退出代码0


救救孩子吧,不然要挂科了{:9_221:}


isdkz 发表于 2023-5-30 16:24:26

在你的代码中,你在调用video_demo()之后,读取了拍摄的照片。但是video_demo()退出时,已经拍摄并保存了图片,然后释放了摄像头。因此,你需要在保存图片后立即读取图片。你可以在video_demo()函数中完成这个操作。

下面是我对你的代码的一些修改,可以实现在拍摄并保存图片后立即读取并显示图片:

import cv2

def video_demo():
    print('开始')
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)# 电脑自身摄像头
    i = 0# 定时装置初始值
    photoname = 1# 文件名序号初始值

    while True:
      i = i + 1
      ret, frame = cap.read()
      frame = cv2.flip(frame, 1)# 图片左右调换
      cv2.imshow('window', frame)

      if i == 50:# 定时装置,定时截屏,可以修改。
            filename = str(photoname) + '.png'# filename为图像名字,将photoname作为编号命名保存的截图
            filepath = 'E:/asdfghj' + '\\' + filename
            cv2.imwrite(filepath, frame)# 截图 前面为放在桌面的路径 frame为此时的图像
            print(filename + '保存成功')# 打印保存成功
            i = 0# 清零

            # 读取并显示图片
            img = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)
            cv2.imshow('Read Image', img)

            photoname = photoname + 1
            if photoname >= 2:# 最多截图20张 然后退出(如果调用photoname = 1 不用break为不断覆盖图片)
                break
      if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    # 释放资源
    cap.release()

video_demo()
cv2.destroyAllWindows()


这段代码中, cv2.imshow('Read Image', img)这行是新加入的,用于显示读取的图片。在保存图片后,立即读取图片并显示。为了防止路径错误,我创建了一个filepath变量用于保存图片的完整路径,并在读取图片时使用。

这应该可以解决你的问题,如果你有其他问题,欢迎继续提问。

sfqxx 发表于 2023-5-30 17:57:24

你好,可以将摄像头采集到的帧存储为变量,再在循环结束后读取照片进行图像识别。修改后的代码如下:


import cv2

def video_demo():
    print('开始')
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)# 电脑自身摄像头
    i = 0# 定时装置初始值
    frames = []# 存储帧

    while True:
      i = i + 1
      reg, frame = cap.read()
      frame = cv2.flip(frame, 1)# 图片左右调换
      cv2.imshow('window', frame)

      if i == 50:# 定时装置,定时截屏,可以修改。
            frames.append(frame)
            i = 0# 清零

            if len(frames) >= 2:# 最多截图2张 然后退出
                break
               
      if cv2.waitKey(1) & 0xff == ord('q'):
            break
            
    # 释放资源
    cap.release()
    cv2.destroyAllWindows()

    if len(frames) > 0:
      filename = 'capture.png'
      cv2.imwrite(filename, frames)# 存储第一张图片
      print(filename + '保存成功')

img = cv2.imread('capture.png', cv2.IMREAD_GRAYSCALE);
video_demo()
# 在此处添加图像识别代码,对img进行处理
cv2.imshow('image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

这里使用了一个列表`frames`来存储摄像头每一帧,当获取到第二帧时就退出循环,将第一帧保存为文件。在后面的图像识别代码中,读取这个文件并进行处理。

同时,要注意修改之前的读取图像代码,修改为读取名为'capture.png'的图片:


import cv2

img = cv2.imread('capture.png', cv2.IMREAD_GRAYSCALE);
# 在此处添加完成后续的图像处理和识别代码,对`img`进行处理。

求最佳答案{:10_254:}

学不会C的苦命人 发表于 2023-5-30 19:26:24

isdkz 发表于 2023-5-30 16:24
在你的代码中,你在调用video_demo()之后,读取了拍摄的照片。但是video_demo()退出时,已经拍摄并 ...

谢谢大佬,可以查看照片了,但现在又有一个问题,我该怎么对图片进行处理。我写的程序是这样的
import cv2

def video_demo():
    print('开始')
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)# 电脑自身摄像头
    i = 0# 定时装置初始值
    photoname = 1# 文件名序号初始值

    while True:
      i = i + 1
      reg, frame = cap.read()
      frame = cv2.flip(frame, 1)# 图片左右调换
      cv2.imshow('window', frame)

      if i == 50:# 定时装置,定时截屏,可以修改。
            filename = str(photoname) + '.png'# filename为图像名字,将photoname作为编号命名保存的截图
            filepath = 'E:/asdfghj' + '\\' + filename
            cv2.imwrite('E:/asdfghj' + '\\' + filename, frame)# 截图 前面为放在桌面的路径 frame为此时的图像
            print(filename + '保存成功')# 打印保存成功
            i = 0# 清零
            #读取图片
            img = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)

            #变HSV
            hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
            c_low1 = (85,150,150)
            c_high1 = (95,255,255)
            #大津法二值化
            dst = cv2.inRange(hsv,c_low1,c_high1)

            cv2.imshow('Read Image', img)
            cv2.waitKey(0)
            photoname = photoname + 1
            if photoname >= 2:# 最多截图20张 然后退出(如果调用photoname = 1 不用break为不断覆盖图片)
                # photoname = 1
                break
      if cv2.waitKey(1) & 0xff == ord('q'):
            break
    # 释放资源
    cap.release()

video_demo()
cv2.destroyAllWindows()
然后这个照片也显示不出来了,显示的结果如下
Traceback (most recent call last):
File "D:\pythonProject\tuxiangduqushiyantwo\main.py", line 42, in <module>
    video_demo()
File "D:\pythonProject\tuxiangduqushiyantwo\main.py", line 25, in video_demo
    hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
cv2.error: OpenCV(4.7.0) d:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\color.simd_helpers.hpp:92: error: (-2:Unspecified error) in function '__cdecl cv::impl::`anonymous-namespace'::CvtHelper<struct cv::impl::`anonymous namespace'::Set<3,4,-1>,struct cv::impl::A0x416a7d27::Set<3,-1,-1>,struct cv::impl::A0x416a7d27::Set<0,5,-1>,2>::CvtHelper(const class cv::_InputArray &,const class cv::_OutputArray &,int)'
> Invalid number of channels in input image:
>   'VScn::contains(scn)'
> where
>   'scn' is 1

请问这个该怎么办呢

isdkz 发表于 2023-5-30 19:30:25

学不会C的苦命人 发表于 2023-5-30 19:26
谢谢大佬,可以查看照片了,但现在又有一个问题,我该怎么对图片进行处理。我写的程序是这样的
import c ...

你的问题出在读取图片时将其转换为灰度图像(cv2.IMREAD_GRAYSCALE),然后试图将灰度图像从BGR转换为HSV格式。灰度图像只有一个颜色通道,而BGR和HSV格式都需要3个颜色通道(蓝色、绿色、红色或色相、饱和度、明度)。这就是为什么你得到一个错误说输入图像的通道数量无效。

你应该直接读取图像,然后转换为HSV格式。在下面的代码中,我已经做了这个修改:

import cv2

def video_demo():
    print('开始')
    cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)# 电脑自身摄像头
    i = 0# 定时装置初始值
    photoname = 1# 文件名序号初始值

    while True:
      i = i + 1
      ret, frame = cap.read()
      frame = cv2.flip(frame, 1)# 图片左右调换
      cv2.imshow('window', frame)

      if i == 50:# 定时装置,定时截屏,可以修改。
            filename = str(photoname) + '.png'# filename为图像名字,将photoname作为编号命名保存的截图
            filepath = 'E:/asdfghj' + '\\' + filename
            cv2.imwrite(filepath, frame)# 截图 前面为放在桌面的路径 frame为此时的图像
            print(filename + '保存成功')# 打印保存成功
            i = 0# 清零

            # 读取图片
            img = cv2.imread(filepath)

            # 变HSV
            hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
            c_low1 = (85,150,150)
            c_high1 = (95,255,255)
            # 大津法二值化
            dst = cv2.inRange(hsv,c_low1,c_high1)

            cv2.imshow('Processed Image', dst)
            cv2.waitKey(0)

            photoname = photoname + 1
            if photoname >= 2:# 最多截图20张 然后退出(如果调用photoname = 1 不用break为不断覆盖图片)
                break
      if cv2.waitKey(1) & 0xff == ord('q'):
            break
    # 释放资源
    cap.release()

video_demo()
cv2.destroyAllWindows()

在这段代码中,我已将读取图像的代码从img = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)修改为img = cv2.imread(filepath) ,这样img将是BGR格式的彩色图像,可以被转换为HSV格式。

另外,我改变了最后一行cv2.imshow的参数,让它显示经过处理的图像dst ,而不是原始图像img 。如果你想同时显示原始图像和处理后的图像,你可以添加一行cv2.imshow('Original Image', img) 。
页: [1]
查看完整版本: 如何用python opencv调用摄像头拍照的同时读取这张照片