在 OpenCV2 中找到最接近图像中心的轮廓
Finding the contour closest to image center in OpenCV2
我正在尝试使用 openCV2 从静态地图自动描绘教堂和大教堂的轮廓。
简而言之,我是:
- 从 this Wikipedia page 抓取建筑物的坐标。
- 使用 Python 库 Folium 创建以这些坐标为中心的地图。
- 将地图保存为 jpg 图片。
- 应用openCV2的
findContours
方法来描绘建筑物的轮廓。
我最初假设大教堂将是几百米内最大的建筑,所以我按面积对等高线进行了排序 this PyImageSearch tutorial:
contours = sorted(contours, key = cv2.contourArea, reverse = True)[0:1]
在某些情况下,这就像一个魅力,比如圣彼得大教堂:
然而,根据城市和选择的缩放级别,我经常碰巧选择附近的建筑物,这些建筑物实际上比教堂大:
我正在考虑选择离图像中心最近的轮廓。
一个选项是计算地图中所有等高线的中心,然后确定离图像市中心最近的点,但我想知道是否有更简单的解决方案。
任何帮助将不胜感激!
我使用 cv2.moments(contour)
如 this article 所示获得每个轮廓的中心。然后你可以使用scipy.spatial
模块中的distance.euclidian
来计算每个轮廓到图像中心的距离。
示例图片:
代码:
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)
结果图片:
我正在尝试使用 openCV2 从静态地图自动描绘教堂和大教堂的轮廓。
简而言之,我是:
- 从 this Wikipedia page 抓取建筑物的坐标。
- 使用 Python 库 Folium 创建以这些坐标为中心的地图。
- 将地图保存为 jpg 图片。
- 应用openCV2的
findContours
方法来描绘建筑物的轮廓。
我最初假设大教堂将是几百米内最大的建筑,所以我按面积对等高线进行了排序 this PyImageSearch tutorial:
contours = sorted(contours, key = cv2.contourArea, reverse = True)[0:1]
在某些情况下,这就像一个魅力,比如圣彼得大教堂:
然而,根据城市和选择的缩放级别,我经常碰巧选择附近的建筑物,这些建筑物实际上比教堂大:
我正在考虑选择离图像中心最近的轮廓。
一个选项是计算地图中所有等高线的中心,然后确定离图像市中心最近的点,但我想知道是否有更简单的解决方案。 任何帮助将不胜感激!
我使用 cv2.moments(contour)
如 this article 所示获得每个轮廓的中心。然后你可以使用scipy.spatial
模块中的distance.euclidian
来计算每个轮廓到图像中心的距离。
示例图片:
代码:
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)