假设我有一个像这样的图像:
我想获得构成该线的点(x,y)的列表。有没有办法在Python中这样做?如果我将图像加载为矩阵,我会得到矩阵的一些元素,表明有"黑色"。问题是线可能有一些宽度,因此会有许多矩阵元素对应于线上的同一点。我怎样才能解决这个问题?有没有直接的方式来做我需要的事情?
提前致谢。
答案 0 :(得分:1)
这实际上是一个复杂的问题。您需要提取图像中所有黑色的点,然后找到一种方法将它们压缩为一组大致跟踪路径的数据。
import requests
from PIL import Image
import numpy as np
import io
from sklearn.cluster import mean_shift
# get the image
url = 'https://i.stack.imgur.com/qKAk5.png'
res = requests.get(url)
# set the content as a file pointer object
fp = io.BytesIO(res.content)
# load the image to PIL
img = Image.open(fp)
# convert the image to gray-scale and load it to a numpy array
# need to transpose because the X and Y are swapped in PIL
# need [:,::-1] because pngs are indexed from the upper left
arr = np.array(img.convert('L')).T[:,::-1]
# get indices where there line is the pixel values is dark, ie <100
indices = np.argwhere(arr < 100)
到目前为止,我们有索引或(x,y)位置,其中出现暗像素。但是有更多的方式比你需要的更多。为了减少数量,我们可以使用聚类技术来减少点数。这里适用mean_shift
聚类技术。它将内核分配给一组点,然后迭代地让附近的点慢慢拉到一起。主要参数是内核的带宽,即拉力的“宽度”。
# this shows how many clusters are formed per bandwidth
for x in np.arange(.5,5.6,.25):
print('{:.2f}: '.format(x), end='')
print(len(mean_shift(indices, bandwidth=x)[0]))
# returns:
0.50: 1697
0.75: 1697
1.00: 539
1.25: 397
1.50: 364
1.75: 343
2.00: 277
2.25: 247
2.50: 232
2.75: 221
3.00: 194
3.25: 175
3.50: 165
3.75: 160
4.00: 156
4.25: 138
4.50: 139
4.75: 133
5.00: 120
5.25: 111
5.50: 112
因此,对于该线的约200点近似,您可以使用3.0的带宽。
points, labels = mean_shift(indices, bandwidth=3.0)
# lets plot the points
import matplotlib.pyplot as plt
plt.scatter(points[:,0], points[:,1])
答案 1 :(得分:0)
你可以使用opencv:
import cv2
import numpy as np
import matplotlib.pyplot as plt
image = cv2.imread('squiggly.png', cv2.IMREAD_GRAYSCALE)
ret, image = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)
scatter = np.where(image==0)
x,y = scatter[1],-scatter[0]
plt.scatter(x,y,color='blue',marker='.',s=0.2)
plt.show()