Process folder with images using OpenCV

This post is a followup to https://madflex.de/posts/find-and-crop-using-opencv/.

The goal is to process a folder with images to get the ones with a display in it. To find errors a version with a rectangle and height/width is saved and a version with the display cropped.

The resulting rectangular image is:

rect_image

And the crop:

crop_image

Sourcecode:

from pathlib import Path
import imutils
import cv2


def find_and_crop(filename):
    fn = filename.stem
    year, month = str(filename.parents[0]).split("/")[-2:]
    output_rect = filename.parents[3] / "output" / f"{year}-{month}-{fn}-rect.png"
    output_crop = filename.parents[3] / "output" / f"{year}-{month}-{fn}-crop.png"

    image = cv2.imread(str(filename))
    image = image[300:1300, 500:1400]
    height, width, channels = image.shape

    # rotate
    center = (width / 2, height / 2)
    angle = 87
    M = cv2.getRotationMatrix2D(center, angle, 1)
    image = cv2.warpAffine(image, M, (height, width))

    # resize
    resized = imutils.resize(image, width=300)
    ratio = height / float(resized.shape[0])

    # greyscale
    gray = cv2.cvtColor(image.copy(), cv2.COLOR_BGR2GRAY)
    gray = cv2.blur(gray, (11, 11))
    thresh = cv2.threshold(gray, 60, 255, cv2.THRESH_BINARY)[1]

    contours, hierarchy = cv2.findContours(thresh, 1, 2)
    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        if w > 200 and w < 400 and h > 100 and h < 230:
            break
    else:
        # set because "break" was not triggered -> no rectangle / crop
        x = None

    if x:
        rect = cv2.rectangle(image.copy(), (x, y), (x + w, y + h), (0, 255, 0), 2)

        rect = cv2.putText(
            rect,
            f"h:{h} | w:{w}",
            (10, 50),
            fontFace=cv2.FONT_HERSHEY_SIMPLEX,
            fontScale=1.5,
            color=(255, 0, 0),
            lineType=3,
        )

        cv2.imwrite(str(output_rect), rect)

        # crop image and increase brightness
        cropped = image[y : y + h, x : x + w]
        contrast = cv2.convertScaleAbs(cropped, alpha=3, beta=0)
        cv2.imwrite(str(output_crop), contrast)


def main(base_folder):
    base_folder = Path("../images/")

    for fn in sorted(base_folder.glob("201*/*/*jpg")):
        find_and_crop(fn)

I now have 3700 cropped displays with digits in it. The next step is now detecting the digits (for real this time).