Сохранить обнаруженный QR-код из живого видеопотока как изображение, используя Python OpenCV - PullRequest
4 голосов
/ 11 февраля 2020

Я работаю над проектом, использующим Python (3.7) и OpenCV 2, в котором мне нужно обнаружить QR-код и сохранить его как изображение. Я успешно выполнил часть определения, но не знаю, как это сделать. Я сохраняю 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

Как сохранить обнаруженное область (QR-код) как изображение?

Обновление: ниже обновленный код для автоматической загрузки изображения, но это не работает.

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

1 Ответ

2 голосов
/ 11 февраля 2020

Предполагая, что (x, y, w, h) = barcode.rect возвращает те же значения, что и x,y,w,h = cv2.boundingRect(contour), здесь приведена визуализация для обрезки области интереса из изображения

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

Рассмотрим (0,0) в качестве верхнего левого угла изображение с слева направо в качестве направления х и сверху вниз в качестве направления у. Если у нас есть (x1,y1) как верхний левый угол и (x2,y2) как нижний правый край области интереса, мы можем использовать Numpy срезку, чтобы обрезать изображение с помощью:

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

Но обычно мы не будет иметь правую нижнюю вершину. В типичных случаях мы будем выполнять итерации по контурам, где прямоугольные координаты angular ROI можно найти с помощью cv2.boundingRect(). Кроме того, если бы мы хотели сохранить несколько 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...