在OpenCV2中找到最接近图像中心的轮廓

She*_*don 3 python opencv contour

我正在尝试使用 openCV2 从静态地图自动描绘教堂和大教堂的轮廓。

简而言之,我是:

  • 从这个维基百科页面抓取建筑物的坐标。
  • 使用 Python 库 Folium 创建以这些坐标为中心的地图。
  • 将地图另存为 jpg 图像。
  • 应用openCV2的findContours方法来描绘建筑物的轮廓。

我最初假设大教堂将是几百米内最大的建筑,因此我按照PyImageSearch 教程按面积对轮廓进行排序:

contours = sorted(contours, key = cv2.contourArea, reverse = True)[0:1]
Run Code Online (Sandbox Code Playgroud)

在某些情况下,这就像一种魅力,比如圣彼得大教堂:

在此输入图像描述

然而,根据城市和所选的缩放级别,我经常碰巧选择附近实际上比教堂大的建筑物:

在此输入图像描述

我正在考虑选择最接近图像中心的轮廓。

一种选择是计算地图中所有轮廓的中心,然后确定距图像城市中心最近的点,但我想知道是否有更简单的解决方案。任何帮助将不胜感激!

Dav*_*alb 5

我使用本文cv2.moments(contour)中所示的方法来获取每个轮廓的中心。然后您可以使用该模块来计算每个轮廓到图像中心的距离。distance.euclidianscipy.spatial

示例图片:

在此输入图像描述

代码:

    import cv2
    import numpy as np
    from scipy.spatial import distance
    
    
    sample_img = cv2.imread("sample_buildings.png")
    
    # convert to black and white color space
    sample_img_grey = cv2.cvtColor(sample_img, cv2.COLOR_BGR2GRAY)
    contours, hierarchy = cv2.findContours(sample_img_grey, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    #find center of image and draw it (blue circle)
    image_center = np.asarray(sample_img_grey.shape) / 2
    image_center = tuple(image_center.astype('int32'))
    cv2.circle(sample_img, image_center, 3, (255, 100, 0), 2)
    
    buildings = []
    for contour in contours:
        # find center of each contour
        M = cv2.moments(contour)
        center_X = int(M["m10"] / M["m00"])
        center_Y = int(M["m01"] / M["m00"])
        contour_center = (center_X, center_Y)
    
        # calculate distance to image_center
        distances_to_center = (distance.euclidean(image_center, contour_center))
    
        # save to a list of dictionaries
        buildings.append({'contour': contour, 'center': contour_center, 'distance_to_center': distances_to_center})
    
        # draw each contour (red)
        cv2.drawContours(sample_img, [contour], 0, (0, 50, 255), 2)
        M = cv2.moments(contour)
    
        # draw center of contour (green)
        cv2.circle(sample_img, contour_center, 3, (100, 255, 0), 2)
    
    # sort the buildings
    sorted_buildings = sorted(buildings, key=lambda i: i['distance_to_center'])
    
    # find contour of closest building to center and draw it (blue)
    center_building_contour = sorted_buildings[0]['contour']
    cv2.drawContours(sample_img, [center_building_contour], 0, (255, 0, 0), 2)
    
    cv2.imshow("Image", sample_img)
    cv2.waitKey(0)
Run Code Online (Sandbox Code Playgroud)

结果图像:

在此输入图像描述