这是改版后的代码, 之前有在2群发过原始代码,原始代码有点乱就修改了一下
参考文章(吾爱破解):https://www.52pojie.cn/forum.php?mod=viewthread&tid=1288315&highlight=%C4%B3%CD%F8%D5%BEweb%B6%CB%C5%C0%B3%E6
原文:https://blog.youkuaiyun.com/mixintu/article/details/112396945
这是Java_S
大佬的哔哩哔哩视频讲解哦: https://www.bilibili.com/video/BV1NK4y1s7Aq?from=search&seid=269553927107791704
import sys
sys.path.append("..")
import cv2
import time
import numpy as np
from concurrent.futures import ThreadPoolExecutor
# --------------------------------
from utils.single import SingleType
# from utils.output import exceptOutput,info,result,cv_show
class Yuan8(metaclass=SingleType):
"""
识别文字
"""
# @exceptOutput(msg='去除杂乱的背景色 - 异常')
def remove_bg(self,im,h, w):
# 去掉黑椒点的图像
im[np.all(im == [0, 0, 0], axis=-1)] = (255, 255, 255)
# reshape:展平成n行3列的二维数组
colors, counts = np.unique(np.array(im).reshape(-1, 3), axis=0, return_counts=True)
# 方便看数量对应的像素值【推荐使用元组生成式】
info_dict = {counts[i]: colors[i].tolist() for i, v in enumerate(counts) if 550 <= int(v) <= 3000}
# 第一步:移除了背景的图片------------------------------------------------------------------------------------
lines_and_character_rgbs = info_dict.values()
mask = np.zeros((h, w, 3), np.uint8) + 255
for rgb in lines_and_character_rgbs:
mask[np.all(im == rgb, axis=-1)] = im[np.all(im == rgb, axis=-1)] # 文字和线条替换回原色
# cv_show("mask", mask) # 移除了背景的图片
return mask, lines_and_character_rgbs
# @exceptOutput(msg='文字和线条处理 - 异常')
def run(self, name, image):
im = cv2.imread(image)
h, w = im.shape[0:2]
mask, lines_and_character_rgbs = self.remove_bg(im,h, w)
# 获取全部线条的像素值
line_list = []
for y in range(225): # y轴
for x in range(215): # x轴
if mask[x, y].sum() != 765:
li = mask[x, y].tolist()
if 0 < y < 12 or 110 < y < 120 or 210 < y < 220:
line_list.append(li)
if 0 < x < 9 or 100 < x < 110 or 200 < x < 209:
line_list.append(li)
# 线条颜色:(unique:去除其中重复的元素 axis:按列排序)
lines_rgbs = np.unique(np.array(line_list), axis=0)
# 文字颜色【这里写的不好】
character_rgbs = np.array([i for i in lines_and_character_rgbs if i not in lines_rgbs])
# print(lines_rgbs, character_rgbs)
# 第二步(1):文字线条全部黑化的图片-------------------------------------------------------------------------------
'''
mask1 = np.copy(mask)
# 开运算:先进行腐蚀操作,再进行膨胀操作
mask1[np.any(mask1 != [255, 255, 255], axis=-1)] = [0, 0, 0] # 全部黑化
MORPH_OPEN = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, np.ones((4, 4), np.int8))
cv_show('MORPH_OPEN', MORPH_OPEN)
'''
# 第二步(2):文字全部黑化的图片---------------------------------------------------------------------------白色线条
'''
mask2 = np.copy(mask)
for rgb in lines_rgbs: # 根据线条颜色(移除线条在 axis=-1:图片维度的最后一维中操作)
mask2[np.all(mask2 == rgb, axis=-1)] = [255, 255, 255] # 线条白化
mask2[np.any(mask2 != [255, 255, 255], axis=-1)] = [0, 0, 0] # 全部黑化
MORPH_OPEN2 = cv2.morphologyEx(mask2, cv2.MORPH_OPEN, np.ones((3, 3), np.int8)) # 开运算:先进行腐蚀操作,再进行膨胀操作
cv_show("MORPH_OPEN2-2", MORPH_OPEN2) # 移除了线条的图片
'''
# 第二步(3):文字全部黑化的图片---------------------------------------------------------------------------油色线条
'''
mask3 = np.copy(mask)
for rgb in lines_rgbs: # 根据线条颜色
mask3[np.all(mask3 == rgb, axis=-1)] = [0, 0, 0] # 全部黑化
MORPH_OPEN3 = cv2.morphologyEx(mask3, cv2.MORPH_OPEN, np.ones((3, 4), np.int8))
cv_show("MORPH_OPEN3-3", MORPH_OPEN3) # 移除了线条的图片
'''
# 第二步(4):线条全部黑化的图片---------------------------------------------------------------------------油色文字
'''
mask4 = np.copy(mask)
for rgb in character_rgbs: # 根据文字颜色
mask4[np.all(mask4 == rgb, axis=-1)] = [0, 0, 0] # 全部黑化
MORPH_OPEN4 = cv2.morphologyEx(mask4, cv2.MORPH_OPEN, np.ones((3, 3), np.int8))
cv_show("MORPH_OPEN-4", MORPH_OPEN4) # 移除了线条的图片
'''
# 第二步(5):线条全部黑化的图片---------------------------------------------------------------------------油色文字
''' '''
mask4 = np.copy(mask)
for rgb in lines_rgbs: # 根据文字颜色
mask4[np.all(mask4 == rgb, axis=-1)] = [255, 255, 255] # 线条白化
mask4[np.any(mask4 != [255, 255, 255], axis=-1)] = [0, 0, 0] # 全部黑化
for rgb in lines_rgbs:
mask4[np.all(mask == rgb, axis=-1)] = mask[np.all(mask == rgb, axis=-1)] # # 线条替换回原色
MORPH_OPEN4 = cv2.morphologyEx(mask4, cv2.MORPH_OPEN, np.ones((3, 3), np.int8))
cv2.imshow("MORPH_OPEN-4", MORPH_OPEN4) # 移除了线条的图片
cv2.waitKey(0)
# 第三步:接上识别模块进行处理--------------------------------------------------------------------------------------
# ......
# @exceptOutput(msg='普通处理 - 异常')
def yuan8_discern(my_slider, name, image):
'''
server.py 普通调用的接口
'''
return my_slider.run(name,image) # 移动距离
# @exceptOutput(msg='线程处理 - 异常')
def yuan8_discern_thread(pool,my_slider,name,image):
'''
server.py 可支持多线程调用的接口
'''
move = pool.submit(yuan8_discern, my_slider, name, image).result()
return move
if __name__ == '__main__':
start_time = time.perf_counter()
print("开始")
pool = ThreadPoolExecutor(max_workers=3, thread_name_prefix='thread')
my_slider = Yuan8()
params = {
# '1':'./yuan8/mi1.png',
# '2':'./yuan8/mi2.png',
# '3':'./yuan8/mi3.png',
# '4':'./yuan8/mi4.png',
# '5':'./yuan8/mi5.png',
# '6':'./yuan8/mi6.png',
# '7':'./yuan8/mi7.png',
# '8':'./yuan8/mi8.png',
# '9':'./yuan8/mi9.png',
'10':'./yuan8/mi10.png',
# 测试线程池
# ......
}
for i,image in params.items():
# my_slider = Yuan8()
# move = yuan8_discern(my_slider, f"task-{i}", image)
move = yuan8_discern_thread(pool, my_slider, f"task-{i}", image)
# result(f"{id(my_slider)} task-{i} {imag·e} {move}")
# print(f"task-{i} {image} {move}")
pool.shutdown()
print("结束 总运行时长: %f秒"% (time.perf_counter() - start_time))
cv2.waitKey(0)
cv2.destroyAllWindows()