【问题标题】:Scan a perspective image in Python在 Python 中扫描透视图像
【发布时间】:2021-04-13 14:55:40
【问题描述】:

我正在尝试准备几张从不同角度拍摄的乐谱图像,以便我可以进行 OMR。

我尝试过变换和旋转它们,但没有帮助,我想我需要调整图像的视角

我试过了:

def rotate_image(mat, angle):
    height, width = mat.shape[:2] # image shape has 3 dimensions
    image_center = (width/2, height/2) # getRotationMatrix2D needs coordinates in reverse order (width, height) compared to shape

    rotation_mat = cv2.getRotationMatrix2D(image_center, angle, 1.)

    # rotation calculates the cos and sin, taking absolutes of those.
    abs_cos = abs(rotation_mat[0,0])
    abs_sin = abs(rotation_mat[0,1])

    # find the new width and height bounds
    bound_w = int(height * abs_sin + width * abs_cos)
    bound_h = int(height * abs_cos + width * abs_sin)

    # subtract old image center (bringing image back to origo) and adding the new image center coordinates
    rotation_mat[0, 2] += bound_w/2 - image_center[0]
    rotation_mat[1, 2] += bound_h/2 - image_center[1]

    # rotate image with the new bounds and translated rotation matrix
    rotated_mat = cv2.warpAffine(mat, rotation_mat, (bound_w, bound_h), borderValue=[255,255,255,0])
    return rotated_mat

# the first call
def our_rotate(RGBImage):
    angle = getAngle(RGBImage)
    rot = rotate_image(RGBImage,angle)
    return rot

【问题讨论】:

  • “我尝试了很多方法来修复这张图片的视角”,展示你尝试过的How to Ask
  • 我将通过编写我尝试过的所有算法来继续编辑帖子
  • 如果您可以标记或检测四个角,则使用 opencv 的单应变换应该可以很好地处理这个问题。稍后我会发布更详细的回复作为答案。

标签: python python-3.x opencv image-processing scikit-image


【解决方案1】:

单应性的思想是,给定一组对应点,我们可以计算将第一组点扭曲到第二组所需的矩阵。如果我们挑出乐谱的角并告诉它们变形为一个矩形,那么我们得到的单应矩阵将完全执行该操作。通过将该扭曲应用于所有点,我们可以纠正图像。

结果的好坏取决于页面开始时的平整度、镜头畸变程度(您可以使用 opencv 通过一些棋盘校准来消除畸变)以及选择角落的准确度。

代码如下:

import cv2
import math
import numpy as np

# corner clicks
corners = []; # assuming clockwise from top-left: [top-left, top-right, bottom-right, bottom-left]
def clicky(event, x, y, flags, param):
    # get globals
    global corners;

    # check for mouse click
    if event == cv2.EVENT_LBUTTONUP:
        if len(corners) < 4:
            corners.append((x,y));

# returns 2d distance
def dist2D(one, two):
    dx = one[0] - two[0];
    dy = one[1] - two[1];
    return math.sqrt(dx*dx + dy*dy);


# load image
img = cv2.imread("sheet.png");

# make a set window
cv2.namedWindow("Image")
cv2.setMouseCallback("Image", clicky)

# loop
done = False;
while not done or len(corners) < 4:
    # make a copy
    copy = img.copy();

    # draw corners
    for corner in corners:
        copy = cv2.circle(copy, corner, 4, (0,0,255), -1);

    # show
    cv2.imshow("Image", copy);
    key = cv2.waitKey(1);

    # check keys
    done = key == ord('q');

# destination points (a rectangle)
margin = 100;
half = int(margin / 2);
height = int(dist2D(corners[0], corners[3]));
width = int(dist2D(corners[0], corners[1]));
rect = [];
rect.append([half,half]);
rect.append([half+width,half]);
rect.append([half+width,half+height]);
rect.append([half,half+height]);

# get the homography matrix
corners = np.array(corners);
rect = np.array(rect);
hmat, ret = cv2.findHomography(corners, rect);

# warp image
warped = cv2.warpPerspective(img, hmat, (width+margin, height+margin));

# show
cv2.imshow("Warped", warped);
cv2.imwrite("marked.png", copy);
cv2.imwrite("warped.png", warped);
cv2.waitKey(0);

【讨论】:

  • 非常感谢,但我在大学的助教告诉我,他不希望用户做任何事情,因为他正在通过在不允许的 docker 环境中测试项目来对项目进行测试如果您可以帮助我让计算机自行检测 4 个角以使任何图像看起来像这些图像,我们将进行任何用户交互
  • 如果所有图片的背景大多为白色,您可以通过扫描黑色像素并寻找最极端(最左、最右、上、下)位置的四个像素来检测角落。
  • 实际上,这似乎是一个非常脆弱的策略。那可能真的很容易坏。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-19
  • 2016-09-08
  • 2011-05-08
  • 2012-08-28
相关资源
最近更新 更多