获取图像上显示屏 4 个角的坐标

pet*_*ter 6 python opencv numpy image-processing

我试图获得图像上的屏幕(显示)的 4 个角。我有两张从同一位置拍摄的图像(所以我认为好的起点是提取两张图像/第一和第二图像/之间的差异)。只是屏幕上的图像发生了变化。所以我想获得显示屏角的上/左下/右(X,Y)坐标。

我正在使用带有 cv2 和 numpy 的 python 2.7(如果可能不使用其他模块)。不幸的是,我不知道如何获得这些坐标。

请问有什么想法吗?PS示例代码会很棒并且非常感谢,非常感谢

在此处输入图片说明 在此处输入图片说明

最后结果:

在此处输入图片说明

Ale*_*lex 5

我使用图像之间的差异创建了一个新的解决方案,并从中找到了轮廓。我在底部使用霍夫线处理留下了旧的解决方案。

import numpy as np
import cv2


def main():
    im1 = cv2.imread('s123/ss1.jpg')
    im2 = cv2.imread('s123/ss2.jpg')

    gray1 = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)

    # Try to match the two image's exposures
    gray1 = cv2.equalizeHist(gray1)
    gray2 = cv2.equalizeHist(gray2)

    # Find the difference and threshold it
    diff = cv2.absdiff(gray1, gray2)
    _, thresh = cv2.threshold(diff, 50, 255, cv2.THRESH_BINARY)

    # Filtering to improve the thresholded image
    thresh = cv2.medianBlur(thresh, 5)
    thresh = cv2.dilate(thresh, None, iterations=2)

    # Calculate contours and find the largest one
    _, cnts, hierachy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnt = max([c for c in cnts], key=lambda x: cv2.contourArea(x))

    cv2.drawContours(im1, [cnt], 0, (0, 255, 0), 3)

    # Remove the concavities
    hull = cv2.convexHull(cnt)
    cv2.drawContours(im1, [hull], 0, (255, 0, 0), 2)
    hull = [tuple(p[0]) for p in hull]

    # Find all the corners
    tr = max(hull, key=lambda x: x[0] - x[1])
    cv2.circle(im1, tr, 3, (0, 0, 255), -1)

    tl = min(hull, key=lambda x: x[0] + x[1])
    cv2.circle(im1, tl, 3, (0, 0, 255), -1)

    br = max(hull, key=lambda x: x[0] + x[1])
    cv2.circle(im1, br, 3, (0, 0, 255), -1)

    bl = min(hull, key=lambda x: x[0] - x[1])
    cv2.circle(im1, bl, 3, (0, 0, 255), -1)

    cv2.imshow('im1', im1)
    cv2.imshow('diff', thresh)

    cv2.waitKey(0)


if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

输出

这种方法的缺点是需要在屏幕上有很大的差异(即 1&2 工作但 1&3 不起作用但是 2&3 工作,因为 2 大部分是白色的)。如果您想要更强大的方法,请尝试使用需要更多图像的背景减法器


我平均了两个图像,然后使用霍夫线处理来找到线条。然后我过滤了这些,然后找到了交点:

import numpy as np
import cv2


# Code to find line intersections. From https://stackoverflow.com/a/20677983
def line_intersection(line1, line2):
    xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
    ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])

    def det(a, b):
        return a[0] * b[1] - a[1] * b[0]

    div = det(xdiff, ydiff)
    if div == 0:
        return -1, -1

    d = (det(*line1), det(*line2))
    x = det(d, xdiff) / div
    y = det(d, ydiff) / div
    return x, y


def main():
    im1 = cv2.imread('GaJrr.jpg')
    im2 = cv2.imread('kR2pl.jpg')

    gray1 = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
    gray2 = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)

    # Average the images
    diff = cv2.addWeighted(gray1, 0.5, gray2, 0.5, 0)

    # Canny and Hough lines
    c = cv2.Canny(diff, 89, 200)
    lines = cv2.HoughLines(c, 1, np.pi / 180, 100, None, 0, 0)

    pts = []

    # Create segments for each line
    if lines is not None:
        for i in range(len(lines)):
            rho = lines[i][0][0]
            theta = lines[i][0][1]
            a = np.cos(theta)
            b = np.sin(theta)
            x0 = a * rho
            y0 = b * rho
            pt1 = np.array([int(x0 + 1000 * (-b)), int(y0 + 1000 * a)])
            pt2 = np.array([int(x0 - 1000 * (-b)), int(y0 - 1000 * a)])

            if not any([np.linalg.norm(pt1 - p[0]) < 100 for p in pts]):    # Filter out lines too close to each other
                pts.append(np.array([pt1, pt2]))

                cv2.line(im1, tuple(pt1), tuple(pt2), (0, 0, 255), 1, cv2.LINE_AA)

    for pt in pts:
        for comp in pts:
            intersect = np.array(line_intersection(pt, comp))
            if any(intersect < 0) or intersect[0] > im1.shape[1] or intersect[1] > im1.shape[0]:    # Filter out off-screen intersections
                continue

            intersect = np.asarray(intersect, dtype=int)
            print(intersect)
            cv2.circle(im1, tuple(intersect), 3, (0, 255, 0), -1)

    cv2.imshow('im1', im1)

    cv2.waitKey(0)


if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

输出

这绝对可以优化一堆。