gpt4 book ai didi

python - 使车牌图像变形为正面平行

转载 作者:行者123 更新时间:2023-12-02 16:16:03 27 4
gpt4 key购买 nike

我正在尝试拍摄车牌的图像,以便随后可以进行一些图像处理以在车牌周围绘制轮廓,然后可以使用它扭曲透 View ,然后在其上查看车牌正面。不幸的是,我在尝试围绕已处理的图像绘制轮廓时出现错误。具体来说,我收到了Invalid shape (4, 1, 2) for the image data错误。我不太确定如何解决此问题,因为我知道我处理的所有其他图像都很好。只是当我尝试绘制轮廓时,出现了问题。

import cv2
import numpy as np
from matplotlib import pyplot as plt

kernel = np.ones((3,3))
image = cv2.imread('NoPlate0.jpg')

def getContours(img):
biggest = np.array([])
maxArea = 0

contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cnt in contours:
area = cv2.contourArea(cnt)
if area > 500:
cv2.drawContours(imgContour, cnt, -1, (255, 0, 0), 3)
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt,0.02*peri, True)
if area > maxArea and len(approx) == 4:
biggest = approx
maxArea = area
return biggest

imgGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
imgBlur = cv2.GaussianBlur(imgGray,(5,5),1)
imgCanny = cv2.Canny(imgBlur,150,200)
imgDial = cv2.dilate(imgCanny,kernel,iterations=2)
imgThres = cv2.erode(imgDial,kernel,iterations=2)
imgContour = image.copy()

titles = ['original', 'Blur', 'Canny', 'Dialte', 'Threshold', 'Contours' ]
images = [image, imgBlur, imgCanny, imgDial, imgThres, getContours(imgThres)]

for i in range(6):
plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])

plt.show()

我得到的确切错误是:
TypeError: Invalid shape (4, 1, 2) for image data

我正在使用以下图像作为输入:

license_plate

最佳答案

您的函数仅返回沿轮廓的实际点,然后尝试在其上调用plt.imshow。这就是为什么您会收到此错误的原因。您需要做的是将此轮廓与cv2.drawContour结合使用以获取所需的内容。在这种情况下,我们应该重组getContours函数,使其返回坐标(以便以后使用)和在图像本身上绘制的实际轮廓。不必更改imgContour并将其视为全局变量,而只需绘制一次此图像,它将是循环中找到的最大轮廓:

def getContours(img):
biggest = np.array([])
maxArea = 0
imgContour = img.copy() # Change - make a copy of the image to return
contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
index = None
for i, cnt in enumerate(contours): # Change - also provide index
area = cv2.contourArea(cnt)
if area > 500:
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt,0.02*peri, True)
if area > maxArea and len(approx) == 4:
biggest = approx
maxArea = area
index = i # Also save index to contour

if index is not None: # Draw the biggest contour on the image
cv2.drawContours(imgContour, contours, index, (255, 0, 0), 3)

return biggest, imgContour # Change - also return drawn image

最后,我们可以通过以下方式在您的总体代码中使用它:

import cv2
import numpy as np
from matplotlib import pyplot as plt

kernel = np.ones((3,3))
image = cv2.imread('NoPlate0.jpg')

imgGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
imgBlur = cv2.GaussianBlur(imgGray,(5,5),1)
imgCanny = cv2.Canny(imgBlur,150,200)
imgDial = cv2.dilate(imgCanny,kernel,iterations=2)
imgThres = cv2.erode(imgDial,kernel,iterations=2)
biggest, imgContour = getContours(imgThres) # Change

titles = ['original', 'Blur', 'Canny', 'Dilate', 'Threshold', 'Contours']
images = [image, imgBlur, imgCanny, imgDial, imgThres, imgContour] # Change

for i in range(6):
plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray')
plt.title(titles[i])

plt.show()

最后要注意的是,如果要变形车牌图像以使其与图像平面平行,则可以使用 cv2.getPerspectiveTransform定义从原始源图像(源点)到变形图像(目标点)的单应性),然后使用 cv2.warpPerspective最终使图像变形。请注意,源点和目标点的方式需要对其进行排序,以便它们的对应位置在透 View 中匹配。也就是说,如果定义区域四边形的一组点中的第一个点位于左上角,则源点和目标点都应同时定义左上角。为此,您可以找到源和目标的四边形的质心,然后找到从质心到每个角的 Angular ,并通过对 Angular 进行排序来对它们进行排序。

这是我编写的执行此功能的以下函数 order_points:

def order_points(pts):
# Step 1: Find centre of object
center = np.mean(pts)

# Step 2: Move coordinate system to centre of object
shifted = pts - center

# Step #3: Find angles subtended from centroid to each corner point
theta = np.arctan2(shifted[:, 0], shifted[:, 1])

# Step #4: Return vertices ordered by theta
ind = np.argsort(theta)
return pts[ind]

最后,根据您返回的角点,尝试执行以下操作:

src = np.squeeze(biggest).astype(np.float32) # Source points
height = image.shape[0]
width = image.shape[1]
# Destination points
dst = np.float32([[0, 0], [0, height - 1], [width - 1, 0], [width - 1, height - 1]])

# Order the points correctly
src = order_points(src)
dst = order_points(dst)

# Get the perspective transform
M = cv2.getPerspectiveTransform(src, dst)

# Warp the image
img_shape = (width, height)
warped = cv2.warpPerspective(img, M, img_shape, flags=cv2.INTER_LINEAR)
src是包含车牌的源多边形的四个角。请注意,因为它们是从 cv2.approxPolyDP返回的,它们将是 4 x 1 x 2的NumPy整数数组。您将需要删除单例第二维并将其转换为32位浮点,以便它们可以与 cv2.getPerspectiveTransform一起使用。 dst是目标点,源多边形中的每个角均映射到实际输出图像尺寸的角点,该尺寸将与输入图像的大小相同。要记住的最后一件事是,使用 cv2.warpPerspective将图像的大小指定为 (width, height)

如果您最终想要将所有这些集成在一起并使 getContours函数返回变形的图像,我们可以很容易地做到这一点。我们必须修改一些东西才能使它按预期工作:
  • getContours还将获取原始的RGB图像,以便我们可以正确地显示轮廓并更好地了解车牌的定位方式。
  • 如上所示,添加逻辑以扭曲getContours内部的图像。
  • 更改绘图代码以也包括此变形图像,并从getContours返回变形图像。
  • 略微修改绘图代码,以便在Matplotlib中显示原始图像,因为cv2.imread读取BGR格式的图像,但是Matplotlib期望图像为RGB格式。

  • 因此:

    import cv2
    import numpy as np
    from matplotlib import pyplot as plt

    def order_points(pts):
    # Step 1: Find centre of object
    center = np.mean(pts)

    # Step 2: Move coordinate system to centre of object
    shifted = pts - center

    # Step #3: Find angles subtended from centroid to each corner point
    theta = np.arctan2(shifted[:, 0], shifted[:, 1])

    # Step #4: Return vertices ordered by theta
    ind = np.argsort(theta)
    return pts[ind]

    def getContours(img, orig): # Change - pass the original image too
    biggest = np.array([])
    maxArea = 0
    imgContour = orig.copy() # Make a copy of the original image to return
    contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    index = None
    for i, cnt in enumerate(contours): # Change - also provide index
    area = cv2.contourArea(cnt)
    if area > 500:
    peri = cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt,0.02*peri, True)
    if area > maxArea and len(approx) == 4:
    biggest = approx
    maxArea = area
    index = i # Also save index to contour

    warped = None # Stores the warped license plate image
    if index is not None: # Draw the biggest contour on the image
    cv2.drawContours(imgContour, contours, index, (255, 0, 0), 3)

    src = np.squeeze(biggest).astype(np.float32) # Source points
    height = image.shape[0]
    width = image.shape[1]
    # Destination points
    dst = np.float32([[0, 0], [0, height - 1], [width - 1, 0], [width - 1, height - 1]])

    # Order the points correctly
    biggest = order_points(src)
    dst = order_points(dst)

    # Get the perspective transform
    M = cv2.getPerspectiveTransform(src, dst)

    # Warp the image
    img_shape = (width, height)
    warped = cv2.warpPerspective(orig, M, img_shape, flags=cv2.INTER_LINEAR)

    return biggest, imgContour, warped # Change - also return drawn image

    kernel = np.ones((3,3))
    image = cv2.imread('NoPlate0.jpg')

    imgGray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    imgBlur = cv2.GaussianBlur(imgGray,(5,5),1)
    imgCanny = cv2.Canny(imgBlur,150,200)
    imgDial = cv2.dilate(imgCanny,kernel,iterations=2)
    imgThres = cv2.erode(imgDial,kernel,iterations=2)
    biggest, imgContour, warped = getContours(imgThres, image) # Change

    titles = ['Original', 'Blur', 'Canny', 'Dilate', 'Threshold', 'Contours', 'Warped'] # Change - also show warped image
    images = [image[...,::-1], imgBlur, imgCanny, imgDial, imgThres, imgContour, warped] # Change

    # Change - Also show contour drawn image + warped image
    for i in range(5):
    plt.subplot(3, 3, i+1)
    plt.imshow(images[i], cmap='gray')
    plt.title(titles[i])

    plt.subplot(3, 3, 6)
    plt.imshow(images[-2])
    plt.title(titles[-2])

    plt.subplot(3, 3, 8)
    plt.imshow(images[-1])
    plt.title(titles[-1])

    plt.show()

    我得到的数字现在是:

    Final Figure

    关于python - 使车牌图像变形为正面平行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62295185/

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