gpt4 book ai didi

python - 分割车牌字符

转载 作者:太空狗 更新时间:2023-10-29 17:22:13 25 4
gpt4 key购买 nike

我在从车牌图像中分割字符时遇到问题。
我已经应用了以下方法来提取车牌字符"

  • 自适应阈值车牌图像。
  • 选择具有特定纵横比的轮廓。

  • 如果附加文件中的车牌图像中有任何阴影,由于二值化不当,我无法正确分割字符。图像中的阴影合并图像中的相邻字符。

    我对具有不同窗口大小的图像进行了阈值处理。结果附后。如果图像中有阴影,如何从图像中分割字符?我正在使用 OpenCV。

    License plate image with shade

    threshoded image 1

    thresholded image 2

    thresholded image 3

    我在 OpenCV 中使用了以下函数来限制我的车牌图像:
    cvAdaptiveThreshold(licensePlateImg, threshImg, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY_INV, wind);

    我尝试了不同的窗口大小( wind )和不同的 adaptiveMethod ( ADAPTIVE_THRESH_MEAN_C and ADAPTIVE_THRESH_GAUSSIAN_C )
    得到阈值图像。

    最佳答案

    在开始之前,我知道您正在寻求在 OpenCV C++ 中实现该算法,但我的算法需要 FFT 和 numpy / scipy包非常棒。因此,我将使用 Python 在 OpenCV 中为您提供该算法的实现。该代码实际上与 C++ API 非常相似,您可以轻松地将其转录过来。这样,它最大限度地减少了我学习(或者更确切地说是重新学习......)API所需的时间,我宁愿给你算法和我为执行这项任务所做的步骤,而不是浪费任何时间.

    因此,我将向您概述我将要做什么。然后,我将向您展示使用 numpy, scipy 的 Python 代码。和 OpenCV 包。作为对使用 MATLAB 的人的奖励,我将向您展示 MATLAB 等效程序,其中包含可启动的 MATLAB 代码!

    你能做的就是尝试使用 homomorphic filtering .在基本术语中,我们可以根据照度和反射率的乘积来表示图像。假设照明缓慢变化并且是动态范围的主要贡献者。这本质上是低频内容。反射率代表物体的细节,并假设变化迅速。这也是局部对比度的主要贡献者,并且本质上是高频内容。

    图像可以表示为 产品 这两个。同态过滤尝试并拆分这些组件,然后我们单独过滤它们。完成后,我们将结果合并在一起。由于这是一个乘法模型,习惯上使用 日志操作,以便我们可以将乘积表示为两项之和。这两个项被单独过滤,缩放以强调或不强调它们对图像的贡献,求和,然后取反对数。

    阴影是由照明引起的,所以我们可以做的是减少这种阴影对图像的影响。我们还可以提高反射率,这样我们可以获得更好的边缘,因为边缘与高频信息相关。

    我们通常使用低通滤波器过滤照明,而使用高通滤波器过滤反射。在这种情况下,我将选择 sigma 为 10 的高斯内核作为低通滤波器。取1可以得到高通滤波器并用低通滤波器减去。我将图像转换到对数域,然后使用低通和高通滤波器在频域中过滤图像。然后我缩放低通和高通结果,将这些组件添加回来,然后取反对数。该图像现在更适合阈值处理,因为图像的变化很小。

    我做的额外后处理是对图像进行阈值处理。字母比整体背景更暗,因此任何低于某个阈值的像素都将被归类为文本。我选择了强度为 65 的阈值。在此之后,我还清除了所有接触边界的像素,然后删除图像中总面积小于 160 (MATLAB) 或 120 (Python) 像素的任何区域。我还裁剪了图像的一些列,因为我们的分析不需要它们。

    这里有一些警告给你:

    警告 #1 - 移除边框

    删除任何接触边框的像素是 不是 内置于 OpenCV 中。但是,MATLAB 有一个等效项,称为 imclearborder .我将在我的 MATLAB 代码中使用它,但对于 OpenCV,这是以下算法:

  • 找出图像中的所有轮廓
  • 对于图像中的每个轮廓,检查是否有任何轮廓像素在图像的边界内
  • 如果有,请标记此轮廓以进行删除
  • 对于我们要删除的每个轮廓,只需将整个轮廓绘制为黑色

  • 我创建了一个名为 imclearborder(imgBW, radius) 的方法在我的代码中,其中 radius是要清除边界内的多少像素。

    警告 #2 - 删除特定区域下方的像素区域

    删除小于一定数量的任何区域也是 不是 在 OpenCV 中实现。在 MATLAB 中,这可以使用 bwareaopen 方便地给出。 .其基本算法是:
  • 找出图像中的所有轮廓
  • 如果要填充内部,分析每个轮廓的区域填充了多少
  • 任何小于一定数量的区域,通过用黑色填充内部来清除此轮廓

  • 我创建了一个名为 bwareaopen(imgBW) 的方法这对我们来说是这样的。

    警告 #3 - 用于移除像素区域的区域参数

    对于 Python 代码,我不得不尝试使用这个参数,我选择了 120。160 用于 MATLAB。对于python,120去掉了一些不需要的字符。我猜我的实现 bwareaopen与 MATLAB 相比是不同的,这可能是我得到不同结果的原因。

    闲话少说,代码如下。请注意,我没有使用 空间过滤 .您可以使用 filter2D在 OpenCV 中并使用高斯核对这个图像进行卷积,但我没有这样做,因为在使用低通和高通滤波器时,同态滤波传统上是在频域中完成的。您可以使用空间过滤来探索这一点,但您还必须知道 尺寸 事先准备好你的内核。使用频域滤波,您只需要知道滤波器的标准偏差,与两个参数相比,这只是一个参数。

    此外,对于 Python 代码,我将您的图像下载到了我的计算机上并运行了脚本。对于 MATLAB,您可以在使用图像处理工具箱读取图像时直接引用图像的超链接。

    Python代码
    import cv2 # For OpenCV modules (For Image I/O and Contour Finding)
    import numpy as np # For general purpose array manipulation
    import scipy.fftpack # For FFT2

    #### imclearborder definition

    def imclearborder(imgBW, radius):

    # Given a black and white image, first find all of its contours
    imgBWcopy = imgBW.copy()
    contours,hierarchy = cv2.findContours(imgBWcopy.copy(), cv2.RETR_LIST,
    cv2.CHAIN_APPROX_SIMPLE)

    # Get dimensions of image
    imgRows = imgBW.shape[0]
    imgCols = imgBW.shape[1]

    contourList = [] # ID list of contours that touch the border

    # For each contour...
    for idx in np.arange(len(contours)):
    # Get the i'th contour
    cnt = contours[idx]

    # Look at each point in the contour
    for pt in cnt:
    rowCnt = pt[0][1]
    colCnt = pt[0][0]

    # If this is within the radius of the border
    # this contour goes bye bye!
    check1 = (rowCnt >= 0 and rowCnt < radius) or (rowCnt >= imgRows-1-radius and rowCnt < imgRows)
    check2 = (colCnt >= 0 and colCnt < radius) or (colCnt >= imgCols-1-radius and colCnt < imgCols)

    if check1 or check2:
    contourList.append(idx)
    break

    for idx in contourList:
    cv2.drawContours(imgBWcopy, contours, idx, (0,0,0), -1)

    return imgBWcopy

    #### bwareaopen definition
    def bwareaopen(imgBW, areaPixels):
    # Given a black and white image, first find all of its contours
    imgBWcopy = imgBW.copy()
    contours,hierarchy = cv2.findContours(imgBWcopy.copy(), cv2.RETR_LIST,
    cv2.CHAIN_APPROX_SIMPLE)

    # For each contour, determine its total occupying area
    for idx in np.arange(len(contours)):
    area = cv2.contourArea(contours[idx])
    if (area >= 0 and area <= areaPixels):
    cv2.drawContours(imgBWcopy, contours, idx, (0,0,0), -1)

    return imgBWcopy

    #### Main program

    # Read in image
    img = cv2.imread('5DnwY.jpg', 0)

    # Number of rows and columns
    rows = img.shape[0]
    cols = img.shape[1]

    # Remove some columns from the beginning and end
    img = img[:, 59:cols-20]

    # Number of rows and columns
    rows = img.shape[0]
    cols = img.shape[1]

    # Convert image to 0 to 1, then do log(1 + I)
    imgLog = np.log1p(np.array(img, dtype="float") / 255)

    # Create Gaussian mask of sigma = 10
    M = 2*rows + 1
    N = 2*cols + 1
    sigma = 10
    (X,Y) = np.meshgrid(np.linspace(0,N-1,N), np.linspace(0,M-1,M))
    centerX = np.ceil(N/2)
    centerY = np.ceil(M/2)
    gaussianNumerator = (X - centerX)**2 + (Y - centerY)**2

    # Low pass and high pass filters
    Hlow = np.exp(-gaussianNumerator / (2*sigma*sigma))
    Hhigh = 1 - Hlow

    # Move origin of filters so that it's at the top left corner to
    # match with the input image
    HlowShift = scipy.fftpack.ifftshift(Hlow.copy())
    HhighShift = scipy.fftpack.ifftshift(Hhigh.copy())

    # Filter the image and crop
    If = scipy.fftpack.fft2(imgLog.copy(), (M,N))
    Ioutlow = scipy.real(scipy.fftpack.ifft2(If.copy() * HlowShift, (M,N)))
    Iouthigh = scipy.real(scipy.fftpack.ifft2(If.copy() * HhighShift, (M,N)))

    # Set scaling factors and add
    gamma1 = 0.3
    gamma2 = 1.5
    Iout = gamma1*Ioutlow[0:rows,0:cols] + gamma2*Iouthigh[0:rows,0:cols]

    # Anti-log then rescale to [0,1]
    Ihmf = np.expm1(Iout)
    Ihmf = (Ihmf - np.min(Ihmf)) / (np.max(Ihmf) - np.min(Ihmf))
    Ihmf2 = np.array(255*Ihmf, dtype="uint8")

    # Threshold the image - Anything below intensity 65 gets set to white
    Ithresh = Ihmf2 < 65
    Ithresh = 255*Ithresh.astype("uint8")

    # Clear off the border. Choose a border radius of 5 pixels
    Iclear = imclearborder(Ithresh, 5)

    # Eliminate regions that have areas below 120 pixels
    Iopen = bwareaopen(Iclear, 120)

    # Show all images
    cv2.imshow('Original Image', img)
    cv2.imshow('Homomorphic Filtered Result', Ihmf2)
    cv2.imshow('Thresholded Result', Ithresh)
    cv2.imshow('Opened Result', Iopen)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    MATLAB 代码
    clear all;
    close all;

    % Read in image
    I = imread('http://i.stack.imgur.com/5DnwY.jpg');

    % Remove some columns from the beginning and end
    I = I(:,60:end-20);

    % Cast to double and do log. We add with 1 to avoid log(0) error.
    I = im2double(I);
    I = log(1 + I);

    % Create Gaussian mask in frequency domain
    % We must specify our mask to be twice the size of the image to avoid
    % aliasing.
    M = 2*size(I,1) + 1;
    N = 2*size(I,2) + 1;
    sigma = 10;
    [X, Y] = meshgrid(1:N,1:M);
    centerX = ceil(N/2);
    centerY = ceil(M/2);
    gaussianNumerator = (X - centerX).^2 + (Y - centerY).^2;

    % Low pass and high pass filters
    Hlow = exp(-gaussianNumerator./(2*sigma.^2));
    Hhigh = 1 - Hlow;

    % Move origin of filters so that it's at the top left corner to match with
    % input image
    Hlow = ifftshift(Hlow);
    Hhigh = ifftshift(Hhigh);

    % Filter the image, and crop
    If = fft2(I, M, N);
    Ioutlow = real(ifft2(Hlow .* If));
    Iouthigh = real(ifft2(Hhigh .* If));

    % Set scaling factors then add
    gamma1 = 0.3;
    gamma2 = 1.5;
    Iout = gamma1*Ioutlow(1:size(I,1),1:size(I,2)) + ...
    gamma2*Iouthigh(1:size(I,1),1:size(I,2));

    % Anti-log then rescale to [0,1]
    Ihmf = exp(Iout) - 1;
    Ihmf = (Ihmf - min(Ihmf(:))) / (max(Ihmf(:)) - min(Ihmf(:)));

    % Threshold the image - Anything below intensity 65 gets set to white
    Ithresh = Ihmf < 65/255;

    % Remove border pixels
    Iclear = imclearborder(Ithresh, 8);

    % Eliminate regions that have areas below 160 pixels
    Iopen = bwareaopen(Iclear, 160);

    % Show all of the results
    figure;
    subplot(4,1,1);
    imshow(I);
    title('Original Image');
    subplot(4,1,2);
    imshow(Ihmf);
    title('Homomorphic Filtered Result');
    subplot(4,1,3);
    imshow(Ithresh);
    title('Thresholded Result');
    subplot(4,1,4);
    imshow(Iopen);
    title('Opened Result');

    这是我得到的结果:

    Python

    请注意,我重新排列了窗口,以便它们在单列中对齐。

    enter image description here

    MATLAB

    enter image description here

    关于python - 分割车牌字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24731810/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com