【问题标题】:Save detected QR code from live video stream as an image using Python OpenCV使用 Python OpenCV 将实时视频流中检测到的二维码保存为图像
【发布时间】:2020-05-27 04:04:17
【问题描述】:

我正在使用 Python(3.7) 和 OpenCV 2 进行一个项目,在该项目中我必须检测 QR 码并将其保存为图像,我已成功完成检测部分但不知道如何保存二维码作为图片?

这是我迄今为止尝试过的:

检测部分代码:

while True:
    frame = vs.read()
    frame = imutils.resize(frame, width=400)
    barcodes = pyzbar.decode(frame)

    for barcode in barcodes:
        (x, y, w, h) = barcode.rect
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
        barcodeData = barcode.data.decode("utf-8")
        barcodeType = barcode.type
        text = "{}".format(barcodeData)
        cv2.putText(frame, '', (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

        if barcodeData not in found:
            csv.write("{}\n".format(barcodeData))
            csv.flush()

            found.clear()
            found.add(barcodeData)

    # Título do Frame
    cv2.imshow("Live Stream Window", frame)
    key = cv2.waitKey(1) & 0xFF

    if key == ord("q"):
        break

如何将检测到的区域(二维码)保存为图片?

更新:下面是自动svae图像的更新代码,但这不起作用。

while True:
    frame = vs.read()
    frame = imutils.resize(frame, width=400)
    original = frame.copy()
    barcodes = pyzbar.decode(frame)
    barcode_num = 0
    frame_dict = {'y': 0, 'w': 0, 'h': 0, 'x': 0}

    for barcode in barcodes:
        (x, y, w, h) = barcode.rect
        print(f'{x}, {y}, {w}, {h}')
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
        ROI = original[y:y + h, x:x + w]
        frame_dict['y'] = y
        frame_dict['x'] = x
        frame_dict['h'] = h
        frame_dict['w'] = w
        barcode_num += 1
        barcodeData = barcode.data.decode("utf-8")
        print(barcodeData)
        barcodeType = barcode.type
        text = "{}".format(barcodeData)
        cv2.putText(frame, '', (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

        if barcodeData not in found:
            csv.write("{}\n".format(barcodeData))
            csv.flush()

            found.clear()
            found.add(barcodeData)

    cv2.imshow("Live Stream Window", frame)
    key = cv2.waitKey(1) & 0xFF

    if key == ord("c"):
        print('c is pressed')
        ROI = original[frame_dict['y']:frame_dict['y'] + frame_dict['h'],
                       frame_dict['x']:frame_dict['x'] + frame_dict['w']]
        cv2.imwrite('barcode_{}.png'.format(barcode_num), ROI)
        pass
    if key == ord("q"):
        break

【问题讨论】:

标签: python opencv machine-learning deep-learning computer-vision


【解决方案1】:

假设(x, y, w, h) = barcode.rect 返回与x,y,w,h = cv2.boundingRect(contour) 相同的值,下面是从图像中裁剪ROI 的可视化效果

-------------------------------------------
|                                         | 
|    (x1, y1)                             |
|      ------------------------           |
|      |                      |           |
|      |                      |           | 
|      |         ROI          |           |  
|      |                      |           |   
|      |                      |           |   
|      |                      |           |       
|      ------------------------           |   
|                           (x2, y2)      |    
|                                         |             
|                                         |             
|                                         |             
-------------------------------------------

(0,0) 视为图像的左上角,从左到右为x 方向,从上到下为y 方向。如果我们将(x1,y1) 作为左上角,(x2,y2) 作为 ROI 的右下角,我们可以使用 Numpy 切片来裁剪图像:

ROI = image[y1:y2, x1:x2]

但通常我们不会有右下角的顶点。在典型情况下,我们将遍历可以使用cv2.boundingRect() 找到矩形 ROI 坐标的轮廓。此外,如果我们想保存多个 ROI,我们可以保留一个计数器

cnts = cv2.findContours(grayscale_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

ROI_number = 0
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    ROI = image[y:y+h, x:x+w]
    cv2.imwrite('ROI_{}.png'.format(ROI_number), ROI)
    ROI_number += 1

回到您的问题,我们可以这样做。请注意,我们复制了框架original = frame.copy(),因为一旦我们使用cv2.rectangle 在图像上绘制,它将绘制到框架上。当我们裁剪它时,我们不想要这个绘制的框架,所以我们从框架的副本中裁剪。

while True:
    frame = vs.read()
    frame = imutils.resize(frame, width=400)
    original = frame.copy()
    barcodes = pyzbar.decode(frame)
    barcode_num = 0

    for barcode in barcodes:
        (x, y, w, h) = barcode.rect
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
        ROI = original[y:y+h, x:x+w]
        cv2.imwrite('barcode_{}.png'.format(barcode_num), ROI)
        barcode_num += 1
        barcodeData = barcode.data.decode("utf-8")
        barcodeType = barcode.type
        text = "{}".format(barcodeData)
        cv2.putText(frame, '', (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

        if barcodeData not in found:
            csv.write("{}\n".format(barcodeData))
            csv.flush()

            found.clear()
            found.add(barcodeData)

    # Título do Frame
    cv2.imshow("Live Stream Window", frame)
    key = cv2.waitKey(1) & 0xFF

    if key == ord("q"):
        break

【讨论】:

  • 我试过你的代码,按“q”键是抓图,意思是退出程序,如何不按“q”键自动抓图直播我们还可以提高捕获图像的质量吗?
  • 您可以添加另一个检查是否按下了其他键来手动保存帧。如果要自动捕获图像,请创建一个计时器以定期保存帧。在不了解您的设置和示例图像的情况下,我无法确切说明如何提高图像质量
  • 您能否更新您的代码以定期自动捕获图像?
  • 我尝试添加一个新的waitKey,但它不起作用。您可以在问题中看到更新的代码。
  • 如果要自动抓图,取出方向键,每帧保存图像
猜你喜欢
  • 2023-01-05
  • 1970-01-01
  • 2023-04-09
  • 2020-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-22
相关资源
最近更新 更多