mirror of
https://github.com/opencv/opencv.git
synced 2024-11-27 20:50:25 +08:00
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.py
This commit is contained in:
parent
e92f1eaa3d
commit
d4fc302c7e
248
samples/python/qrcode.py
Normal file
248
samples/python/qrcode.py
Normal file
@ -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
Block a user