图片似乎有很多小的元素,如标点符号。为了解决这个问题,通过筛选轮廓的面积来忽略小的元素。我们可以设定一个最小面积阈值,例如min_area
,然后仅考虑那些面积大于这个阈值的连通组件(轮廓)。这样,较小的标点符号或其他不希望裁剪的元素就不会被考虑。下面是考虑到最小面积阈值的代码:这里,我添加了一个min_area
参数,设置为300。这意味着小于300像素的连通区域(可能是标点符号或噪声)将不会被考虑。您可以根据需要调整这个值。
好,图片切出来1:1
import cv2
import numpy as np
import os
def slice_characters_from_image(img, min_area=1):
alpha_channel=img[:, :, 3]
_, binary=cv2.threshold(alpha_channel, 0, 255, cv2.THRESH_BINARY)
kernel=np.ones((3,3),np.uint8)
binary=cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=2)
contours, _=cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
slices= []
forcontourincontours:
ifcv2.contourArea(contour) <min_area:
continue
x, y, w, h=cv2.boundingRect(contour)
max_side=max(w, h)
canvas=np.zeros((max_side, max_side, 4), dtype=np.uint8)
x_offset= (max_side-w) //2
y_offset= (max_side-h) //2
canvas[y_offset:y_offset+h, x_offset:x_offset+w] =img[y:y+h, x:x+w]
slices.append(canvas)
returnslices
input_folder = '切片'
output_folder = 'output_slices'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
for img_name in os.listdir(input_folder):
ifimg_name.lower().endswith(('.png', '.jpg', '.jpeg')):
img_path=os.path.join(input_folder, img_name)
img=cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
slices=slice_characters_from_image(img)
fori, slice_imginenumerate(slices):
output_name=os.path.join(output_folder, f'slice_{os.path.splitext(img_name)[0]}_{i}.png')
cv2.imwrite(output_name, slice_img)
print("批量处理完成!")
可以看到了“网”字的问题:字的一部分与其他部分有一些小的间隔或中断,这使得它们被识别为两个独立的连通组件。因此,当进行切片时,它们被视为两个独立的区域并分别被切割。为了处理这种情况,使用形态学的“闭运算”来连接这些小的间隔或中断。闭运算是先进行膨胀操作然后再进行腐蚀操作,可以有效地“关闭”小的空隙。增加了闭运算,增加了对二值化结果的形态学闭运算处理,能有效地处理“网”字或其他具有小间隔的字符。
好,图片比例为1:1,网字也能切出来。
import cv2
import numpy as np
import os
def slice_characters_from_image(img):
alpha_channel=img[:, :, 3]
_, binary=cv2.threshold(alpha_channel, 0, 255, cv2.THRESH_BINARY)
kernel=np.ones((3,3),np.uint8)
binary=cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=2)
contours, _=cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
slices= []
forcontourincontours:
x, y, w, h=cv2.boundingRect(contour)
max_side=max(w, h)
canvas=np.zeros((max_side, max_side, 4), dtype=np.uint8)
x_offset= (max_side-w) //2
y_offset= (max_side-h) //2
canvas[y_offset:y_offset+h, x_offset:x_offset+w] =img[y:y+h, x:x+w]
slices.append(canvas)
returnslices
input_folder = '切片'
output_folder = 'output_slices'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
for img_name in os.listdir(input_folder):
ifimg_name.lower().endswith(('.png', '.jpg', '.jpeg')):
img_path=os.path.join(input_folder, img_name)
img=cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
slices=slice_characters_from_image(img)
fori, slice_imginenumerate(slices):
output_name=os.path.join(output_folder, f'slice_{os.path.splitext(img_name)[0]}_{i}.png')
cv2.imwrite(output_name, slice_img)
print("批量处理完成!")
测试用例
网字可以切出来,字体能切,但图片比例为原始图片大小,字体是单独的,其它部分为透明。
import cv2
import numpy as np
import os
def slice_characters_from_image(img):
alpha_channel=img[:, :, 3]
_, binary=cv2.threshold(alpha_channel, 0, 255, cv2.THRESH_BINARY)
kernel=np.ones((3,3),np.uint8)
binary=cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=2)
contours, _=cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
slices= []
forcontourincontours:
x, y, w, h=cv2.boundingRect(contour)
# 创建一个全透明的图片,与原图大小一致
char_img=np.zeros_like(img)
# 将裁剪的字符放入新图片的对应位置
char_img[y:y+h, x:x+w] =img[y:y+h, x:x+w]
slices.append(char_img)
returnslices
input_folder = '切片'
output_folder = 'output_slices'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
for img_name in os.listdir(input_folder):
ifimg_name.lower().endswith(('.png', '.jpg', '.jpeg')):
img_path=os.path.join(input_folder, img_name)
img=cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
slices=slice_characters_from_image(img)
fori, slice_imginenumerate(slices):
output_name=os.path.join(output_folder, f'slice_{os.path.splitext(img_name)[0]}_{i}.png')
cv2.imwrite(output_name, slice_img)
print("批量处理完成!")
网字切出来了,但宽高比不同。但宽高比相差不多。
import cv2
import numpy as np
import os
def slice_characters_from_image(img):
alpha_channel=img[:, :, 3]
_, binary=cv2.threshold(alpha_channel, 0, 255, cv2.THRESH_BINARY)
# 使用闭运算连接小的间隔
kernel=np.ones((3,3),np.uint8)
binary=cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel, iterations=2)
contours, _=cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
slices= []
forcontourincontours:
x, y, w, h=cv2.boundingRect(contour)
# 增加一个小的边距
margin=5
x=max(0, x-margin)
y=max(0, y-margin)
w=min(w+2*margin, img.shape[1] -x)
h=min(h+2*margin, img.shape[0] -y)
char_img=img[y:y+h, x:x+w]
slices.append(char_img)
returnslices
input_folder = '切片'
output_folder = 'output_slices'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
for img_name in os.listdir(input_folder):
ifimg_name.lower().endswith(('.png', '.jpg', '.jpeg')):
img_path=os.path.join(input_folder, img_name)
img=cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
slices=slice_characters_from_image(img)
fori, slice_imginenumerate(slices):
output_name=os.path.join(output_folder, f'slice_{os.path.splitext(img_name)[0]}_{i}.png')
cv2.imwrite(output_name, slice_img)
print("批量处理完成!")
网字切成了两张图
import cv2
import numpy as np
import os
def slice_characters_from_image(img):
alpha_channel=img[:, :, 3]
_, binary=cv2.threshold(alpha_channel, 0, 255, cv2.THRESH_BINARY)
contours, _=cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
slices= []
forcontourincontours:
x, y, w, h=cv2.boundingRect(contour)
# 增加一个小的边距
margin=5
x=max(0, x-margin)
y=max(0, y-margin)
w=min(w+2*margin, img.shape[1] -x)
h=min(h+2*margin, img.shape[0] -y)
char_img=img[y:y+h, x:x+w]
slices.append(char_img)
returnslices
input_folder = '切片'
output_folder = 'output_slices'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
for img_name in os.listdir(input_folder):
ifimg_name.lower().endswith(('.png', '.jpg', '.jpeg')):
img_path=os.path.join(input_folder, img_name)
img=cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
slices=slice_characters_from_image(img)
fori, slice_imginenumerate(slices):
output_name=os.path.join(output_folder, f'slice_{os.path.splitext(img_name)[0]}_{i}.png')
cv2.imwrite(output_name, slice_img)
print("批量处理完成!")
本代码对于“网”切的不是很好,但学习可以
import cv2
import numpy as np
import os
def slice_characters_from_image(img):
# 获取图像的alpha通道作为二值化的依据
alpha_channel=img[:, :, 3]
_, binary=cv2.threshold(alpha_channel, 0, 255, cv2.THRESH_BINARY)
# 查找连通组件
contours, _=cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
slices= []
forcontourincontours:
x, y, w, h=cv2.boundingRect(contour)
# 根据边界切片
char_img=img[y:y+h, x:x+w]
# 创建一个正方形透明画布
max_side=max(w, h)
canvas=np.zeros((max_side, max_side, 4), dtype=np.uint8)
x_offset= (max_side-w) //2
y_offset= (max_side-h) //2
canvas[y_offset:y_offset+h, x_offset:x_offset+w] =char_img
slices.append(canvas)
returnslices
input_folder = '切片'
output_folder = 'output_slices'
if not os.path.exists(output_folder):
os.makedirs(output_folder)
for img_name in os.listdir(input_folder):
ifimg_name.lower().endswith(('.png', '.jpg', '.jpeg')):
img_path=os.path.join(input_folder, img_name)
img=cv2.imread(img_path, cv2.IMREAD_UNCHANGED)
slices=slice_characters_from_image(img)
fori, slice_imginenumerate(slices):
output_name=os.path.join(output_folder, f'slice_{os.path.splitext(img_name)[0]}_{i}.png')
cv2.imwrite(output_name, slice_img)
print("批量处理完成!")
END
如本资源侵犯了您的权益,请联系投诉邮箱admin@wmphp.com进行举报!我们将在收到邮件的1个小时内处理完毕。
本站仅为平台,发布的资源均为用户投稿或转载!所有资源仅供参考学习使用,请在下载后的24小时内删除,禁止商用!
Wmphp.com(完美源码)助力正版,如您有自己的原创产品,可以联系客服投稿,代理出售!
Wmphp.com(完美源码)客服QQ:136882447
Wmphp.com(完美源码)商务电话(仅对企业客户/个人用户):15120086569 (微信同步)
请注意:本站不提供任何免费的技术咨询服务,为了节约时间,下载前 请确认自己会技术
完美源码 » Python批量将图片中的字体切出单个图片
完美源码 » Python批量将图片中的字体切出单个图片