使用 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]
我有以下使用三种不同书写工具书写的笔迹样本:
看文字,我能看出前两个和最后一个有明显的区别。我的目标是确定每个字母的笔划粗细的近似值,从而允许我根据粗细对它们进行分组。
到目前为止,我已经尝试研究 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]