使用 OpenCV 和 C++ 查找图像中墨迹笔划的宽度

Find the width of an ink stroke in an image using OpenCV & C++

我有以下使用三种不同书写工具书写的笔迹样本:

看文字,我能看出前两个和最后一个有明显的区别。我的目标是确定每个字母的笔划粗细的近似值,从而允许我根据粗细对它们进行分组。

到目前为止,我已经尝试研究 stroke width transform,但我很难将其转化为我的示例。

我能够对图像进行预处理,这样我就只剩下相关测试的轮廓。例如,这里是最后一行的 thick

我建议像您一样使用 cv::findContours 检测轮廓,然后比较边界矩形区域和轮廓区域。字迹越粗系数越大(contourArea/boundingRectArea)。

这个方法可以帮到你。这将计算笔划宽度。

from skimage.feature import peak_local_max
from skimage import img_as_float


def adaptive_thresholding(image):
    output_image = cv2.adaptiveThreshold(image,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,21,2)
    return output_image


def stroke_width(image):
    dist = cv2.distanceTransform(cv2.subtract(255,image), cv2.DIST_L2, 5)
    im = img_as_float(dist)
    coordinates = peak_local_max(im, min_distance=15)
    pixel_strength = []
    for element in coordinates:
        x = element[0]
        y = element[1]
        pixel_strength.append(np.asarray(dist)[x,y])
    mean_pixel_strength = np.asarray(pixel_strength).mean()
    return mean_pixel_strength



image = cv2.imread('Small3.JPG', 0)
process_image = adaptive_thresholding(image)
stroke_width(process_image)

一个 python 的实现可能是这样的,使用 SWTloc.

的笔划宽度变换实现

完全披露:我是这个库的作者。

编辑:Post v2.0.0

变换图像

import swtloc as swt

imgpath = 'images/path_to_image.jpeg'
swtl = swt.SWTLocalizer(image_paths=imgpath)
swtImgObj = swtl.swtimages[0]
# Perform SWT Transformation with numba engine
swt_mat = swtImgObj.transformImage(auto_canny_sigma=1.0, gaussian_blurr=False,
                                   minimum_stroke_width=3, maximum_stroke_width=50,
                                   maximum_angle_deviation=np.pi/3)


本地化字母

localized_letters = swtImgObj.localizeLetters()


绘制每个字母笔画宽度的直方图

import seaborn as sns
import matplotlib.pyplot as plt

all_sws = []
for letter_label, letter in localized_letters.items():
    all_sws.append(letter.stroke_widths_mean)
sns.displot(all_sws, bins=31)

从分布图中可以推断出图像中可能存在三种字体大小的文本 - [3, 15, 27]