opencv——几何变换_透视

1、透视变换

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


"""
透视变换
    对于透视变换,我们需要一个3x3变换矩
    构建这个变换矩需要在输入图像上找4个点,以及它们在输出图像上对应的位置
    注意四个点中的任意三个都不能共线。这个变换矩阵可以用函数 cv.getPerspectiveTransform()构建
    然后把这个矩阵传给函数 getPerspectiveTransform(src, dst[, solveMethod]) -> retval
        返回值:透视变换的3x3矩阵
        参数解析:
            src:原图中四点坐标
            dst:目标图像四点坐标
            solveMethod:传递给cv.solve(DecompTypes) 解决一个或多个线性系统或最小二乘问题
             有以下值可选,DECOMP_LU是默认值
                DECOMP_CHOLESKY = 3
                DECOMP_EIG = 2
                DECOMP_LU = 0
                DECOMP_NORMAL = 16
                DECOMP_QR = 4
                DECOMP_SVD = 1

    透视变换函数原型
    warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) -> dst
        参数解析
            M:透视变换的2X4描述矩阵,由函数getPerspectiveTransform得到
            dsize:输出图像的大小(宽,高)
            flags:插值方式有如下插值法可用
                cv.INTER_NEAREST  最邻近插值,将离新像素所在位置最近的像素像素值赋值给新像素
                cv.INTER_LINEAR  双线性插值, x、y方向临近像素取乘以相应权重并相加赋值给i新的像素值
                cv.INTER_CUBIC  双立方插值, 精度更高,计算量最大,取附近十六个点加权取像素值
                cv.INTER_LANCZOS4  附近像素及原像素加权取值
            borderModer:
                BORDER_CONSTANT = 0  以borderValue值填充边界
                BORDER_DEFAULT = 4   镜像填充
                BORDER_REFLECT = 2  镜像填充
                BORDER_REFLECT101 = 4  镜像填充
                BORDER_REPLICATE = 1  拉伸填充
                BORDER_TRANSPARENT = 5  暂时不知道
                BORDER_WRAP = 3  溢出填充
            borderValue:
                边界填充值


"""
import cv2 as cv
import numpy as np

img = cv.imread('./sudoku.jpg')
h, w, c = img.shape
print(h, w)

pts1 = np.float32([(56, 65), (28, 387), (389, 390), (368, 52)])
pts2 = np.float32([(0, 0), (0, h), (w, h), (w, 0)])

M = cv.getPerspectiveTransform(pts1, pts2)
print(M)
dst = cv.warpPerspective(img, M, (w, h))
# dst = cv.warpPerspective(img, M, (int(w), int(h)),
#                          flags = cv.INTER_CUBIC,
#                          borderMode = cv.BORDER_CONSTANT,
#                          borderValue = (255, 255, 255))

# 在原图中标记这些顶点
cv.circle(img, tuple(pts1[0]), 1, (0, 255, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[1]), 1, (255, 0, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[2]), 1, (255, 255, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[3]), 1, (0, 0, 0), cv.LINE_AA)

# 在目标图中标记顶点
cv.circle(dst, tuple(pts2[0]), 1, (0, 255, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[1]), 1, (255, 0, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[2]), 1, (255, 255, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[3]), 1, (0, 0, 0), cv.LINE_AA)

cv.imwrite('./outputs/sudoku_src.jpg', img)
cv.imwrite('./outputs/sudoku_dst.jpg', dst)

cv.imshow('img', img)
cv.imshow('dst', dst)
cv.waitKey(0)
cv.destroyAllWindows()

2、车牌校正

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


"""
透视变换
    对于透视变换,我们需要一个3x3变换矩
    构建这个变换矩需要在输入图像上找4个点,以及它们在输出图像上对应的位置
    注意四个点中的任意三个都不能共线。这个变换矩阵可以用函数 cv.getPerspectiveTransform()构建
    然后把这个矩阵传给函数 getPerspectiveTransform(src, dst[, solveMethod]) -> retval
        返回值:透视变换的3x3矩阵
        参数解析:
            src:原图中四点坐标
            dst:目标图像四点坐标
            solveMethod:传递给cv.solve(DecompTypes) 解决一个或多个线性系统或最小二乘问题
             有以下值可选,DECOMP_LU是默认值
                DECOMP_CHOLESKY = 3
                DECOMP_EIG = 2
                DECOMP_LU = 0
                DECOMP_NORMAL = 16
                DECOMP_QR = 4
                DECOMP_SVD = 1

    透视变换函数原型
    warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) -> dst
        参数解析
            M:透视变换的2X4描述矩阵,由函数getPerspectiveTransform得到
            dsize:输出图像的大小(宽,高)
            flags:插值方式有如下插值法可用
                cv.INTER_NEAREST  最邻近插值,将离新像素所在位置最近的像素像素值赋值给新像素
                cv.INTER_LINEAR  双线性插值, x、y方向临近像素取乘以相应权重并相加赋值给i新的像素值
                cv.INTER_CUBIC  双立方插值, 精度更高,计算量最大,取附近十六个点加权取像素值
                cv.INTER_LANCZOS4  附近像素及原像素加权取值
            borderModer:
                BORDER_CONSTANT = 0  以borderValue值填充边界
                BORDER_DEFAULT = 4   镜像填充
                BORDER_REFLECT = 2  镜像填充
                BORDER_REFLECT101 = 4  镜像填充
                BORDER_REPLICATE = 1  拉伸填充
                BORDER_TRANSPARENT = 5  暂时不知道
                BORDER_WRAP = 3  溢出填充
            borderValue:
                边界填充值


"""
import cv2 as cv
import numpy as np

img = cv.imread('./plate.jpg')
h, w, c = img.shape
print(h, w)

pts1 = np.float32([(88, 92), (218, 118), (84, 125), (211, 160)])
pts2 = np.float32([(88, 118), (218, 118), (88, 160), (218, 160)])

M = cv.getPerspectiveTransform(pts1, pts2)
print(M)
# dst = cv.warpPerspective(img, M, (w, h))
dst = cv.warpPerspective(img, M, (int(w), int(h)),
                         flags=cv.INTER_CUBIC,
                         borderMode=cv.BORDER_CONSTANT,
                         borderValue=(255, 255, 255))

# 在原图中标记这些顶点
cv.circle(img, tuple(pts1[0]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[1]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[2]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[3]), 1, (0, 0, 255), cv.LINE_AA)

# 在目标图中标记顶点
cv.circle(dst, tuple(pts2[0]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[1]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[2]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[3]), 1, (0, 0, 255), cv.LINE_AA)

cv.imwrite('./outputs/plate_src.jpg', img)
cv.imwrite('./outputs/plate_dst.jpg', dst)

cv.imshow('img', img)
cv.imshow('dst', dst)
cv.waitKey(0)
cv.destroyAllWindows()

3、透视变换练习

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


"""
透视变换
    对于透视变换 ,我们需要一个 3x3 变换矩 。
    在变换前后直线 是直线。
    构建 个变换矩  你需要在输入图像上找 4 个点, 以及他们在输出图 像上对应的位置。
    四个点中的任意三个都不能共线。这个变换矩阵可以用函数 cv.getPerspectiveTransform() 构建。
    然后把这个矩阵传给函数 cv.warpPerspective
        more help(cv.getPerspectiveTransform)
"""
import cv2 as cv
import numpy as np

img = cv.imread('./plate1.jpg')
h, w, c = img.shape
print(img.shape)

cv.namedWindow('img')

pp = np.ones(img.shape, dtype=np.uint8) * 127


def draw_xy(event, x, y, flags, param):
    if flags == cv.EVENT_FLAG_LBUTTON:
        h, w = img.shape[:2]
        x_ = x if x <= w else x - w
        s = '(x:' + str(x_) + ', y:' + str(y) + ')'
        pp = np.ones(img.shape, dtype=np.uint8) * 127
        if x < w:
            cv.putText(pp, s, (20, 70), cv.FONT_HERSHEY_COMPLEX, .9, (255, 255, 255), 1,
                       cv.LINE_AA)
        else:
            cv.putText(pp, s, (20, 140), cv.FONT_HERSHEY_COMPLEX, .9, (255, 255, 255), 1,
                       cv.LINE_AA)
        cv.imshow('img', np.hstack((img, dst, pp)))


cv.setMouseCallback('img', draw_xy)

pts1 = np.float32([[54, 109], [70, 204], [454, 320], [460, 219]])
pts2 = np.float32([[0, 0], [0, h], [w, h], [w, 0]])

M = cv.getPerspectiveTransform(pts1, pts2)
dst = cv.warpPerspective(img, M, (w, h))

# 在原图中标记这些顶点
cv.circle(img, tuple(pts1[0]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[1]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[2]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[3]), 1, (0, 0, 255), cv.LINE_AA)

# 在目标图中标记顶点
cv.circle(dst, tuple(pts2[0]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[1]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[2]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[3]), 1, (0, 0, 255), cv.LINE_AA)

print(dst.shape)
cv.imshow('img', np.hstack((img, dst, pp)))
cv.waitKey(0)
cv.destroyAllWindows()

4、车牌矫正练习

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


import cv2 as cv
import numpy as np


def getXY_min_max(A, B, C, D):
    x_min = min(A[0], C[0])
    y_min = min(A[1], B[1])
    x_max = max(B[0], D[0])
    y_max = max(C[1], D[1])
    return x_min, y_min, x_max, y_max


img_path = './plate.jpg'
img_path = './plate1.jpg'
img = cv.imread(img_path)
h, w = img.shape[:2]

A = (51, 109)
B = (66, 202)
C = (460, 320)
D = (454, 221)

pts1 = np.float32([A, B, C, D])
x_min, y_min, x_max, y_max = getXY_min_max(A, B, C, D)
w = x_max - x_min + 400
h = y_max - y_min - 50
A_ = (0, 0)
B_ = (0, h)
C_ = (w, h)
D_ = (w, 0)
pts2 = np.float32([A_, B_, C_, D_])

M = cv.getPerspectiveTransform(pts1, pts2)
# dst = cv.warpPerspective(img, M, (w, h))
dst = cv.warpPerspective(img, M, (w, h),
                         flags=cv.INTER_CUBIC,
                         borderMode=cv.BORDER_CONSTANT,
                         borderValue=(255, 255, 255))

# 在原图中标记这些顶点
cv.circle(img, tuple(pts1[0]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[1]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[2]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(img, tuple(pts1[3]), 1, (0, 0, 255), cv.LINE_AA)

# 在目标图中标记顶点
cv.circle(dst, tuple(pts2[0]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[1]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[2]), 1, (0, 0, 255), cv.LINE_AA)
cv.circle(dst, tuple(pts2[3]), 1, (0, 0, 255), cv.LINE_AA)

cv.imwrite('./outputs/plate_src.jpg', img)
cv.imwrite('./outputs/plate_dst.jpg', dst)

cv.imshow('img', img)
cv.imshow('dst', dst)
cv.waitKey(0)
cv.destroyAllWindows()

 

©️2020 CSDN 皮肤主题: 我行我“速” 设计师:Amelia_0503 返回首页