鱼C论坛

 找回密码
 立即注册
查看: 1124|回复: 4

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

[复制链接]
发表于 2023-5-30 15:12:12 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
我最近在弄一个结课作业,关于图像识别的,现在的问题是我可以用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()

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


救救孩子吧,不然要挂科了


想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-30 16:24:26 | 显示全部楼层
在你的代码中,你在调用  video_demo()  之后,读取了拍摄的照片。但是  video_demo()  退出时,已经拍摄并保存了图片,然后释放了摄像头。因此,你需要在保存图片后立即读取图片。你可以在  video_demo()  函数中完成这个操作。

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

  1. import cv2

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

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

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

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

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

  26.     # 释放资源
  27.     cap.release()

  28. video_demo()
  29. cv2.destroyAllWindows()
复制代码


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

这应该可以解决你的问题,如果你有其他问题,欢迎继续提问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-30 17:57:24 | 显示全部楼层
你好,可以将摄像头采集到的帧存储为变量,再在循环结束后读取照片进行图像识别。修改后的代码如下:


  1. import cv2

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

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

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

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

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

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


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

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


  1. import cv2

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


求最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 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

请问这个该怎么办呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

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

  1. import cv2

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

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

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

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

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

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

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

  35. video_demo()
  36. 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) 。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-24 08:36

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表