'Specific setting in qrCodeDetector.detectAndDecode() causes memory leak

Intro

I am trying to read QR codes from images that can have them in various orientations. I noticed if I rotate the images and adjust brightness and contrast the chance of finding and reading the QR code increases. Within my dataset, however, sometimes I have images without any codes, in these cases, the script will run over all the possible adjustments before giving up at some point.

Problem

I loop through various brightness and contrast settings and then adjust the main image using

cv2.convertScaleAbs(img, alpha=alpha, beta=beta)

This works well until I run into X == 6 and y == 0. When I reach this point my memory shoots up to the max ram of my system.

Code

I have excluded the part of the code that runs into this issue. The ram increase seems to happen on the step (line 67):

a = qrCodeDetector.detectAndDecode(adjusted)

An image to reproduce the issue:

https://imgpile.com/i/56jN9l

The main code

# libs
import cv2 as cv2
import os
import re
import numpy as np
import multiprocessing as mp
from functools import partial
import gc
from collections import Counter
import linecache
import os
import tracemalloc

newname = "xxxxxxxxxxxxx"

dirs = [r'C:\Users\me\Downloads']

def change_brightness(img, value=30):
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    h, s, v = cv2.split(hsv)
    v = cv2.add(v,value)
    v[v > 255] = 255
    v[v < 0] = 0
    final_hsv = cv2.merge((h, s, v))
    img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
    return img

def rotate_image(image, angle):
  image_center = tuple(np.array(image.shape[1::-1]) / 2)
  rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
  result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
  return result
### the function where the memory leak occurs
def rename_file(filename):
    try:
        print(filename)
        img = cv2.imread(filename)  
        qrCodeDetector = cv2.QRCodeDetector()
        oldfilename = filename
        oldfilename = oldfilename.split('\\')[-1]
        filename = oldfilename.split('\\')[-1]    
        alpha = 10 # Contrast control (1.0-3.0)
        beta = 0 # Brightness control (0-100)
        adjusted = cv2.convertScaleAbs(img, alpha=alpha, beta=beta)
        a = qrCodeDetector.detectAndDecode(adjusted)
        b = a[0]
        a = qrCodeDetector.detectAndDecode(img)
        c = a[0]
        z = 0
        alpha = 5 # Contrast control (1.0-3.0)
        beta = 0 # Brightness control (0-100)
        adjusted = cv2.convertScaleAbs(img, alpha=alpha, beta=beta)
        a = qrCodeDetector.detectAndDecode(adjusted)
        data = ""
        ender = 0    
        while True:
            if ender<1:
                for x in range(21):
                    if len(data)>0:
                        break
                    if ender>0:
                        break
                    for y in range(11):
                        if len(data)>0:
                            break
                        alpha = x # Contrast control (1.0-3.0)
                        beta = y # Brightness control (0-100)
                        adjusted = cv2.convertScaleAbs(img, alpha=alpha, beta=beta) ### Mem leak
                        a = qrCodeDetector.detectAndDecode(adjusted)
                        e = a[0]
                        if len(e)>1:
                            failed = 0
                            data = e
                            ender = 1
                            once = 1
                            break
                        if y>9:
                            if x>19:
                                ender = 1
                                failed = 1                                
            else:
                break
    except:
        print(" ")

qrCodeDetector = cv2.QRCodeDetector()
## making a list of all the photos
list_of_pngs = []
for work_dir in dirs:
    list_of_pngs = []
    os.chdir(work_dir)
    for root, dirs, files in os.walk(work_dir):
        for file in files:
            if file.endswith(".png"):
                rel_dir = os.path.relpath(root, work_dir)
                if 'fdasfdas' in file or 'gafagfadgqgweqwerq' in file:
                    pass
                else:
                    list_of_pngs.append(os.path.join(rel_dir, file))
    print(len(list_of_pngs))
    z= 0
    n=0
    ### read qr codes and rename the file names
    for things in list_of_pngs:
        rename_file(things)
            

    print ("done")


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source