1

Im trying to detect the ROI with the most black pixels for the license plate

Below are the code on the number plate. It is based of the question of How to recognize vehicle license / number plate (ANPR) from an image?.

I modified it a bit b

import cv2
import numpy as np
import imutils
import sys
import glob
import math
import time
import os


def validate_contour(contour, img, aspect_ratio_range, area_range):
    rect = cv2.minAreaRect(contour)
    img_width = img.shape[1]
    img_height = img.shape[0]
    box = cv2.boxPoints(rect)
    box = np.int0(box)

    X = rect[0][0]
    Y = rect[0][1]
    angle = rect[2]
    width = rect[1][0]
    height = rect[1][1]

    angle = (angle + 180) if width < height else (angle + 90)

    output = False

    if (width > 0 and height > 0) and ((width < img_width / 2.0) and (height < img_width / 2.0)):
        aspect_ratio = float(width) / height if width > height else float(height) / width
        if (aspect_ratio >= aspect_ratio_range[0] and aspect_ratio <= aspect_ratio_range[1]):
            if ((height * width > area_range[0]) and (height * width < area_range[1])):

                box_copy = list(box)
                point = box_copy[0]
                del (box_copy[0])
                dists = [((p[0] - point[0]) ** 2 + (p[1] - point[1]) ** 2) for p in box_copy]
                sorted_dists = sorted(dists)
                opposite_point = box_copy[dists.index(sorted_dists[1])]
                tmp_angle = 90

                if abs(point[0] - opposite_point[0]) > 0:
                    tmp_angle = abs(float(point[1] - opposite_point[1])) / abs(point[0] - opposite_point[0])
                tmp_angle = rad_to_deg(math.atan(tmp_angle))

                if tmp_angle <= 45:
                    output = True
    return output


def deg_to_rad(angle):
    return angle * np.pi / 180.0


def rad_to_deg(angle):
    return angle * 180 / np.pi


def enhance(img):
    kernel = np.array([[-1, 0, 1], [-2, 0, 2], [1, 0, 1]])
    return cv2.filter2D(img, -1, kernel)


img = cv2.imread('13.jpg')
input_image = imutils.resize(img, width=500)
raw_image = np.copy(input_image)
img_original = input_image.copy()
img_mask = input_image.copy()
lic_plate = input_image.copy()
contoured = input_image.copy()
gray = cv2.cvtColor(img_original, cv2.COLOR_BGR2GRAY)
gray = enhance(gray)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
gray = cv2.Sobel(gray, -1, 1, 0)
h, sobel = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

se = cv2.getStructuringElement(cv2.MORPH_RECT, (16, 4))
binary = cv2.morphologyEx(sobel, cv2.MORPH_CLOSE, se)
ed_img = np.copy(binary)



contours, _ = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)


for contour in contours:

    aspect_ratio_range = (2.2, 12)  # minimum 2.2 , max 12
    area_range = (500, 18000)

    rectangles = cv2.minAreaRect(contour)  # rect = ((center_x,center_y),(width,height),angle)
    boxes = cv2.boxPoints(rectangles)  # Find four vertices of rectangle from above rect
    boxes = np.int0(boxes)  # Round the values and make it integers
    # print(box)
    all_area = cv2.drawContours(contoured, [boxes], 0, (127, 0, 255), 2)

    if validate_contour(contour, binary, aspect_ratio_range, area_range):
        rect = cv2.minAreaRect(contour)
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        Xs = [i[0] for i in box]
        Ys = [i[1] for i in box]

        x1 = min(Xs)
        x2 = max(Xs)
        y1 = min(Ys)
        y2 = max(Ys)


        angle = rect[2]
        if angle < -45:
            angle += 90

        W = rect[1][0]
        H = rect[1][1]
        aspect_ratio = float(W) / H if W > H else float(H) / W

        center = ((x1 + x2) / 2, (y1 + y2) / 2)
        size = (x2 - x1, y2 - y1)
        M = cv2.getRotationMatrix2D((size[0] / 2, size[1] / 2), angle, 1.0);
        tmp = cv2.getRectSubPix(ed_img, size, center)
        tmp = cv2.warpAffine(tmp, M, size)
   
        TmpW = H if H > W else W
        TmpH = H if H < W else W
        tmp = cv2.getRectSubPix(tmp, (int(TmpW), int(TmpH)), (size[0] / 2, size[1] / 2))
        __, tmp = cv2.threshold(tmp, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

        sortedplate = cv2.drawContours(img_mask, [box], 0, (127, 0, 255), 2)

        white_pixels = 0

        for x in range(tmp.shape[0]):
            for y in range(tmp.shape[1]):
                if tmp[x][y] == 255:
                    white_pixels += 1

        edge_density = float(white_pixels) / (tmp.shape[0] * tmp.shape[1])

        tmp = cv2.getRectSubPix(raw_image, size, center)
        tmp = cv2.warpAffine(tmp, M, size)
        TmpW = H if H > W else W
        TmpH = H if H < W else W
        tmp = cv2.getRectSubPix(tmp, (int(TmpW), int(TmpH)), (size[0] / 2, size[1] / 2))
        # getRectSubPix(  =  Retrieves a pixel rectangle from an image with sub-pixel accuracy.

        if edge_density > 0.5:
            cv2.drawContours(input_image, [box], 0, (127, 0, 255), 2)

cv2.imshow('original', img_original)
cv2.imshow('sobel', sobel)
cv2.imshow('binary', binary)
cv2.imshow("all contours", all_area)
cv2.imshow("sorted", sortedplate)
cv2.imshow("detected", lic_plate)
cv2.waitKey(0)

The image The number plate that needed to detect Example of images lp1 lp2 lp3 lp4

Aiman Azmi
  • 11
  • 3

0 Answers0