mirror of https://github.com/opencv/opencv.git
Merge pull request #16795 from jshiwam:qrsample
Added a sample file for qrcode detection in python * sample python file for qrcode detection added in samples/python * input taken using argparse and the indents were removed * Removed unused variables * updated the format and removed unused variables Removed the use of global variables and used parameterised contructor instead =set multi detection true by default * added detection from camera * samples(python): coding style in qrcode.pypull/17102/head
parent
e92f1eaa3d
commit
d4fc302c7e
1 changed files with 248 additions and 0 deletions
@ -0,0 +1,248 @@ |
||||
#!/usr/bin/env python |
||||
|
||||
''' |
||||
This program detects the QR-codes using OpenCV Library. |
||||
|
||||
Usage: |
||||
qrcode.py |
||||
''' |
||||
|
||||
|
||||
# Python 2/3 compatibility |
||||
from __future__ import print_function |
||||
|
||||
import numpy as np |
||||
import cv2 as cv |
||||
|
||||
import argparse |
||||
import sys |
||||
|
||||
PY3 = sys.version_info[0] == 3 |
||||
if PY3: |
||||
xrange = range |
||||
|
||||
|
||||
class QrSample: |
||||
def __init__(self, args): |
||||
self.fname = '' |
||||
self.fext = '' |
||||
self.fsaveid = 0 |
||||
self.input = args.input |
||||
self.detect = args.detect |
||||
self.out = args.out |
||||
self.multi = args.multi |
||||
self.saveDetections = args.save_detections |
||||
self.saveAll = args.save_all |
||||
|
||||
def getQRModeString(self): |
||||
msg1 = "multi " if self.multi else "" |
||||
msg2 = "detector" if self.detect else "decoder" |
||||
msg = "QR {:s}{:s}".format(msg1, msg2) |
||||
return msg |
||||
|
||||
def drawFPS(self, result, fps): |
||||
message = '{:.2f} FPS({:s})'.format(fps, self.getQRModeString()) |
||||
cv.putText(result, message, (20, 20), 1, |
||||
cv.FONT_HERSHEY_DUPLEX, (0, 0, 255)) |
||||
|
||||
def drawQRCodeContours(self, image, cnt): |
||||
if cnt.size != 0: |
||||
rows, cols, _ = image.shape |
||||
show_radius = 2.813 * ((rows / cols) if rows > cols else (cols / rows)) |
||||
contour_radius = show_radius * 0.4 |
||||
cv.drawContours(image, [cnt], 0, (0, 255, 0), int(round(contour_radius))) |
||||
tpl = cnt.reshape((-1, 2)) |
||||
for x in tuple(tpl.tolist()): |
||||
color = (255, 0, 0) |
||||
cv.circle(image, tuple(x), int(round(contour_radius)), color, -1) |
||||
|
||||
def drawQRCodeResults(self, result, points, decode_info, fps): |
||||
n = len(points) |
||||
if isinstance(decode_info, str): |
||||
decode_info = [decode_info] |
||||
if n > 0: |
||||
for i in range(n): |
||||
cnt = np.array(points[i]).reshape((-1, 1, 2)).astype(np.int32) |
||||
self.drawQRCodeContours(result, cnt) |
||||
msg = 'QR[{:d}]@{} : '.format(i, *(cnt.reshape(1, -1).tolist())) |
||||
print(msg, end="") |
||||
if len(decode_info) > i: |
||||
if decode_info[i]: |
||||
print("'", decode_info[i], "'") |
||||
else: |
||||
print("Can't decode QR code") |
||||
else: |
||||
print("Decode information is not available (disabled)") |
||||
else: |
||||
print("QRCode not detected!") |
||||
self.drawFPS(result, fps) |
||||
|
||||
def runQR(self, qrCode, inputimg): |
||||
if not self.multi: |
||||
if not self.detect: |
||||
decode_info, points, _ = qrCode.detectAndDecode(inputimg) |
||||
dec_info = decode_info |
||||
else: |
||||
_, points = qrCode.detect(inputimg) |
||||
dec_info = [] |
||||
else: |
||||
if not self.detect: |
||||
_, decode_info, points, _ = qrCode.detectAndDecodeMulti( |
||||
inputimg) |
||||
dec_info = decode_info |
||||
else: |
||||
_, points = qrCode.detectMulti(inputimg) |
||||
dec_info = [] |
||||
if points is None: |
||||
points = [] |
||||
return points, dec_info |
||||
|
||||
def DetectQRFrmImage(self, inputfile): |
||||
inputimg = cv.imread(inputfile, cv.IMREAD_COLOR) |
||||
if inputimg is None: |
||||
print('ERROR: Can not read image: {}'.format(inputfile)) |
||||
return |
||||
print('Run {:s} on image [{:d}x{:d}]'.format( |
||||
self.getQRModeString(), inputimg.shape[1], inputimg.shape[0])) |
||||
qrCode = cv.QRCodeDetector() |
||||
count = 10 |
||||
timer = cv.TickMeter() |
||||
for _ in range(count): |
||||
timer.start() |
||||
points, decode_info = self.runQR(qrCode, inputimg) |
||||
timer.stop() |
||||
fps = count / timer.getTimeSec() |
||||
print('FPS: {}'.format(fps)) |
||||
result = inputimg |
||||
self.drawQRCodeResults(result, points, decode_info, fps) |
||||
cv.imshow("QR", result) |
||||
cv.waitKey(1) |
||||
if self.out != '': |
||||
outfile = self.fname + self.fext |
||||
print("Saving Result: {}".format(outfile)) |
||||
cv.imwrite(outfile, result) |
||||
|
||||
print("Press any key to exit ...") |
||||
cv.waitKey(0) |
||||
print("Exit") |
||||
|
||||
def processQRCodeDetection(self, qrcode, frame): |
||||
if len(frame.shape) == 2: |
||||
result = cv.cvtColor(frame, cv.COLOR_GRAY2BGR) |
||||
else: |
||||
result = frame |
||||
print('Run {:s} on video frame [{:d}x{:d}]'.format( |
||||
self.getQRModeString(), frame.shape[1], frame.shape[0])) |
||||
timer = cv.TickMeter() |
||||
timer.start() |
||||
points, decode_info = self.runQR(qrcode, frame) |
||||
timer.stop() |
||||
|
||||
fps = 1 / timer.getTimeSec() |
||||
self.drawQRCodeResults(result, points, decode_info, fps) |
||||
return fps, result, points |
||||
|
||||
def DetectQRFrmCamera(self): |
||||
cap = cv.VideoCapture(0) |
||||
if not cap.isOpened(): |
||||
print("Cannot open the camera") |
||||
return |
||||
print("Press 'm' to switch between detectAndDecode and detectAndDecodeMulti") |
||||
print("Press 'd' to switch between decoder and detector") |
||||
print("Press ' ' (space) to save result into images") |
||||
print("Press 'ESC' to exit") |
||||
|
||||
qrcode = cv.QRCodeDetector() |
||||
|
||||
while True: |
||||
ret, frame = cap.read() |
||||
if not ret: |
||||
print("End of video stream") |
||||
break |
||||
forcesave = self.saveAll |
||||
result = frame |
||||
try: |
||||
fps, result, corners = self.processQRCodeDetection(qrcode, frame) |
||||
print('FPS: {:.2f}'.format(fps)) |
||||
forcesave |= self.saveDetections and (len(corners) != 0) |
||||
except cv.error as e: |
||||
print("Error exception: ", e) |
||||
forcesave = True |
||||
cv.imshow("QR code", result) |
||||
code = cv.waitKey(1) |
||||
if code < 0 and (not forcesave): |
||||
continue |
||||
if code == ord(' ') or forcesave: |
||||
fsuffix = '-{:05d}'.format(self.fsaveid) |
||||
self.fsaveid += 1 |
||||
fname_in = self.fname + fsuffix + "_input.png" |
||||
print("Saving QR code detection result: '{}' ...".format(fname_in)) |
||||
cv.imwrite(fname_in, frame) |
||||
print("Saved") |
||||
if code == ord('m'): |
||||
self.multi = not self.multi |
||||
msg = 'Switching QR code mode ==> {:s}'.format( |
||||
"detectAndDecodeMulti" if self.multi else "detectAndDecode") |
||||
print(msg) |
||||
if code == ord('d'): |
||||
self.detect = not self.detect |
||||
msg = 'Switching QR code mode ==> {:s}'.format( |
||||
"detect" if self.detect else "decode") |
||||
print(msg) |
||||
if code == 27: |
||||
print("'ESC' is pressed. Exiting...") |
||||
break |
||||
print("Exit.") |
||||
|
||||
|
||||
def main(): |
||||
parser = argparse.ArgumentParser( |
||||
description='This program detects the QR-codes input images using OpenCV Library.') |
||||
parser.add_argument( |
||||
'-i', |
||||
'--input', |
||||
help="input image path (for example, 'opencv_extra/testdata/cv/qrcode/multiple/*_qrcodes.png)", |
||||
default="", |
||||
metavar="") |
||||
parser.add_argument( |
||||
'-d', |
||||
'--detect', |
||||
help="detect QR code only (skip decoding) (default: False)", |
||||
action='store_true') |
||||
parser.add_argument( |
||||
'-m', |
||||
'--multi', |
||||
help="enable multiple qr-codes detection", |
||||
action='store_true') |
||||
parser.add_argument( |
||||
'-o', |
||||
'--out', |
||||
help="path to result file (default: qr_code.png)", |
||||
default="qr_code.png", |
||||
metavar="") |
||||
parser.add_argument( |
||||
'--save_detections', |
||||
help="save all QR detections (video mode only)", |
||||
action='store_true') |
||||
parser.add_argument( |
||||
'--save_all', |
||||
help="save all processed frames (video mode only)", |
||||
action='store_true') |
||||
args = parser.parse_args() |
||||
qrinst = QrSample(args) |
||||
if args.out != '': |
||||
index = args.out.rfind('.') |
||||
if index != -1: |
||||
qrinst.fname = args.out[:index] |
||||
qrinst.fext = args.out[index:] |
||||
else: |
||||
qrinst.fname = args.out |
||||
qrinst.fext = ".png" |
||||
if args.input != '': |
||||
qrinst.DetectQRFrmImage(args.input) |
||||
else: |
||||
qrinst.DetectQRFrmCamera() |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
main() |
Loading…
Reference in new issue