OpenCV练习(2)图像校正

  • 1、傅里叶变换 + 霍夫变换+ 直线 + 角度 + 旋转
  • 2、边缘检测 + 霍夫变换 + 直线+角度 + 旋转
  • 3、四点透视 + 角度 + 旋转
  • 4、检测矩形轮廓 + 角度 + 旋转

1.目的

实现类似全能扫面王的图像校正功能

2. 基于轮廓提取和透射变换

基于轮廓提取和透射变换的矫正算法更适用于车牌身份证人民币书本、 发票一类矩形形状而且边界明显的物体矫正。所校正的内容必须要有清晰的完整轮廓。

基本步骤:

  1. 图片灰度化
  2. 二值化/canny边缘检测等操作
  3. 检测轮廓,并筛选出目标轮廓(通过横纵比或面积去除干扰轮廓)
  4. 获取图像顶点
  5. 透视变换

代码:

import cv2
import numpy as np

def contour_to_rect(contour):
    pts = contour.reshape(4, 2)
    print(pts)
    rect = np.zeros((4, 2), dtype = "float32")
    # top-left point has the smallest sum
    # bottom-right has the largest sum
    s = pts.sum(axis = 1)
#     print(s)
    rect[0] = pts[np.argmin(s)]
#     print(pts[np.argmin(s)])
    rect[2] = pts[np.argmax(s)]
    # compute the difference between the points:
    # the top-right will have the minumum difference
    # the bottom-left will have the maximum difference
    diff = np.diff(pts, axis = 1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect

# approximate the contour by a more primitive polygon shape
def approximate_contour(contour):
    peri = cv2.arcLength(contour, True)
    return cv2.approxPolyDP(contour, 0.032 * peri, True)

# 获取顶点坐标
def get_receipt_contour(contours):
    # loop over the contours
    for c in contours:
        approx = approximate_contour(c)
        # if our approximated contour has four points, we can assume it is receipt's rectangle
        if len(approx) == 4:
            return approx


def wrap_perspective(img, rect):
    # unpack rectangle points: top left, top right, bottom right, bottom left
    (tl, tr, br, bl) = rect
    # compute the width of the new image
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    # compute the height of the new image
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    # take the maximum of the width and height values to reach
    # our final dimensions
    maxWidth = max(int(widthA), int(widthB))
    maxHeight = max(int(heightA), int(heightB))
    # destination points which will be used to map the screen to a "scanned" view
    dst = np.array([
        [0, 0],
        [maxWidth - 1, 0],
        [maxWidth - 1, maxHeight - 1],
        [0, maxHeight - 1]], dtype = "float32")
    # calculate the perspective transform matrix
    M = cv2.getPerspectiveTransform(rect, dst)
    # warp the perspective to grab the screen
    return cv2.warpPerspective(img, M, (maxWidth, maxHeight))


if __name__ == "__main__":
    img = cv2.imread("./images/1.png")
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 用高斯滤波处理原图像降噪
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
	#canny边缘检测(仅针对这次的输入图片)
    edged = cv2.Canny(blur, 50, 150)
    contours, h = cv2.findContours(edged.copy(), mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_SIMPLE)
    # img_contours = cv2.drawContours(img.copy(), contours, -1, (0, 0, 255), 3)

    largest_contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5]
    # img_largest_contours = cv2.drawContours( img.copy(), largest_contours, -1, (0, 0, 255), 3)

    receipt_contour = get_receipt_contour(largest_contours)
    # img_receipt_contour = cv2.drawContours(img.copy(), [receipt_contour], -1, (0, 0, 255), 3)

    ori_img = img.copy()
    for coor in contour_to_rect(receipt_contour):
        cv2.circle(ori_img, (int(coor[0]), int(coor[1])), 1, (0, 0, 255), 4)
	# 进行透视变换
    scanned = wrap_perspective(img.copy(), contour_to_rect(receipt_contour))
2.1 图像灰度化 

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

blur = cv2.GaussianBlur(gray, (5, 5), 0)(如果有噪声可以加个高斯滤波)

2.2 canny边缘检测

edged = cv2.Canny(blur, 50, 150) (三个参数分别输入图像,最小阈值,最大阈值)

下图中左为输出,右为边缘检测结果。看起来效果还行

左为所有轮廓绘制,右为面积前五的绘制。可以看到,书中长方形的框并不在检测中,这是因为在进行边缘检测时色差不大导致没检测出来,后续使用闭运算处理将连断出填充完。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值