我有一张图片。这是一封书法字母。
我需要让它充满点,使所有的点相互跟随并对应于字母线的粗细,也就是说,如果字母线变粗,那么点就变大。这是一个例子:
(原来是这封信)
我尝试使用 OpenCV 和 Pillow 处理照片的骨架,但没有成功,如果您帮助我,我将非常高兴,提前谢谢您!
玩了一下,得出了这种相当幼稚的方法,它看起来迭代地放置点,并且似乎产生的结果在某种程度上符合我相信你正在寻找的方向:
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
# read image into numpy array
img = np.asarray(Image.open('../zZfpE.jpg'))
# binarize and coarse-graining
img = (img[::2, ::2, 0] < 128).astype(int)
def make_dots(
img, # 2d np array of 1s and 0s
spd=25, # speed up factor
marg=0.5, # minimum spacing between dots relative to dot size,
max_ds=27, # maximum dot diameter in pixels
min_ds=6, # minimum dot diameter in pixels
):
# start with blank image
img2 = np.zeros(img.shape)
h, w = img.shape
# keep track of areas occupied by dots
occ = set()
ofs = int(spd ** 0.5)
# iterate over dot sizes, decreasing
for t in np.arange(max_ds, min_ds, -5):
# iterate over pixels
for i in range(0, h, ofs):
for j in range(0, w, ofs):
d = 0
# increase dot diameter while 1. within bounds, b. corners of bounding box are black and 3. not already occupied
while (
i + d < h and j + d < w
) and all(
[img[i + d, j + d], img[i, j + d], img[i + d, j]]
) and not any(
[(i + d1, j + d2) in occ for d1, d2 in [(0, d), (d, 0), (d, d)]]
):
d += 1
# consider dot only if exceeding threshold
if d > t:
m = int(marg * d)
ci = i + d // 2
cj = j + d // 2
d2 = (d//2) ** 2
# iterate over pixels in bounding box of dot + margin
for a in range(i-m, i+d+m):
for b in range(j-m, j+d+m):
# mark pixel as occupied by dot
occ.add((a, b))
# if within radius, draw to image
if (ci - a) ** 2 + (cj - b) ** 2 < d2:
img2[a, b] = 1
return img2
plt.imshow(np.hstack((img, make_dots(img))), cmap='gray_r')
plt.axis('off')
plt.tight_layout()
虽然它有点脆弱/老套,但它(根据手头的数据定制参数,或其修改版本)可能仍然有用,如果没有,至少希望能提供一些灵感,因此在这里分享。