环境:python3.6
本篇文章主要讲述的功能是如何把一张包含中文文字的图片转换成英文图片,并且保证图片不受影响。
这里先举个案例:
上图的左边是原始图片没有做任何处理,右边是经过代码处理过翻译后的图片,(由于截图原因导致两张图大小与实际有点偏差)
首先我们先讲一下这个项目的大致思路:
1.识别出图片中全部文字的坐标。
这一点我是借助有道智云的ocr图片识别接口获取坐标信息的
ps:他们家的识别水平一般,坐标不怎么精确
2.对有道智云返回的数据进行清洗。
这个第三方API 返回的json数据是略微复杂的,我们要去他进行提取,和对非中文符号进行过滤(数字,字母也会被识别)
"""判断字符串是否含中文,有为True"""
def check_u(contents):
zhmodel = re.compile(u'[\u4e00-\u9fa5]') #检查中文
#zhmodel = re.compile(u'[^\u4e00-\u9fa5]') #检查非中文
match = zhmodel.search(contents)
if match:
return True
else:
return False
处理过后的数据保存再一个列表中,大致内容如下:
list=[{'商品信息': [328, 28, 458, 28, 458, 65, 328, 65]}, {'品牌:纪诗萱': [253, 190, 452, 190, 452, 230, 253, 230]},
{'货号: 4118': [253, 223, 427, 223, 427, 261, 253, 261]}, {'颜色:藏蓝色黑色': [254, 254, 540, 254, 540, 295, 254, 295]},
{'面料: 80%涤纶20%粘纤': [254, 287, 624, 287, 624, 325, 254, 325]}, {'尺码:M L XL 2XL 3XL 4XL': [254, 319, 698, 319, 698, 356, 254, 356]},
{'版型指数:修身': [229, 398, 434, 398, 434, 435, 229, 435]}, {'长度指数:中长款': [229, 428, 466, 428, 466, 465, 229, 465]},
{'弹性指数:无弹': [517, 397, 721, 397, 721, 435, 517, 435]}, {'厚度指数:常规': [519, 428, 723, 428, 723, 466, 519, 466]},
{'女款大衣尺码 E 腰E': [96, 572, 499, 572, 499, 607, 96, 607]}, {'衣长': [534, 573, 590, 573, 590, 607, 534, 607]},
{'袖长': [625, 571, 681, 571, 681, 607, 625, 607]}, {'手工测量,存在1~3cm的误差,敬请谅解': [124, 838, 663, 838, 663, 876, 124, 876]},
{'洗涤说明': [104, 942, 171, 942, 171, 970, 104, 970]}, {'常规水洗': [280, 956, 350, 956, 350, 983, 280, 983]},
{'不可氯漂': [396, 957, 466, 957, 466, 982, 396, 982]}, {'悬挂晾干': [525, 957, 591, 957, 591, 981, 525, 981]},
{'蒸汽熨烫': [640, 956, 707, 956, 707, 983, 640, 983]}]
拿 “商品信息” 这条数据做例子,后面的 [328, 28, 458, 28, 458, 65, 328, 65] 这个是文字上下左右占的四个坐标
记住:计算机的图片坐标的(0,0)点在左上角。
比例画的有点不对,随手画的,你们能看懂就行。
3.对文字所在区域背景色进行判断
这里逻辑其实并不难,根据文字的四个坐标点 我们可以确定他上下左右四条边的线段方程,让后我们把四条线上的像素点颜色进行统计排序,去中间值为背景色。
4.对文字所在区域进行背景色填充
根据文字的四个坐标点我们也能得出一个矩形范围,即文字所在区域,我们要用背景色对其进行填充,把原有的中文覆盖掉。
效果图如下:
5.对填充区域插入翻译后的英文
中英文翻译仍是借助有道智云的翻译api,这个api的功能就是把中文传过去,返回翻译后的英文,我们拿到英文后再插入到文字所在区域。
效果图:
功能代码如下:
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
import re
# 判断字符串是否含中文,有为True
def check_u(contents):
zhmodel = re.compile(u'[\u4e00-\u9fa5]') #检查中文
#zhmodel = re.compile(u'[^\u4e00-\u9fa5]') #检查非中文
match = zhmodel.search(contents)
if match:
return True
else:
return False
# 找到文字区域,修改背景颜色,然后填写英文
def change_photo(all_lists):
# 拼接图片目录
# 打开图片
img = Image.open("C:/Users/Administrator/Desktop/test.png")
img = img.convert("RGB") # 把图片强制转成RGB
# 图片宽度
width = img.size[0]
# 图片高度
height = img.size[1]
"""对每个坐标区域颜色修改-背景色"""
for i in all_lists:
key, = i
value, = i.values()
lists = value
"""
判断识别的内容是否在对照表,若无,判断是否包含中文,
识别的纯数字符号不做处理
"""
if check_u(key):
words = connect_translate(key)
else:
continue
"""右边边界向右平移1/5高度,若识别区域右边界为图片右边界则不作平移"""
if lists[2] !=width and lists[4]!=width :
add_right_size = int((lists[7] - lists[1]) * 1 / 5)
lists[2] += add_right_size
lists[4] += add_right_size
"""上边界向下平移1/6高度,若识别区域上边界为图片上边界则不作平移"""
if lists[0] !=0 and lists[3]!=0 :
down_right_size = int((lists[7] - lists[1]) * 1 / 6)
lists[1] += down_right_size
lists[3] += down_right_size
"""下边界向上平移1/8高度"""
# up_right_size = int((lists[7] - lists[1]) * 1 / 10)
# lists[5] -= up_right_size
# lists[7] -= up_right_size
"""计算背景颜色"""
RGB_1 = []
RGB_2 = []
RGB_3 = []
for x in range(0, width):
for y in range(0, height):
if (x==lists[0] and lists[1]<y<lists[7]) or (y==lists[1] and lists[0]<x<lists[2]) or (x==lists[2] and lists[3]<y<lists[5]) or (y==lists[5] and lists[6]<x<lists[4]) :
# RGB_data2=(0,255,255)
# img.putpixel((x, y), RGB_data2)
"""获取边框上的全部点的颜色"""
data = (img.getpixel((x,y)))
# 获取坐标颜色R值
RGB_1.append(data[0])
# 获取坐标颜色g值
RGB_2.append(data[1])
# 获取坐标颜色b值
RGB_3.append(data[2])
# 按从小到大排序
RGB_1.sort()
RGB_2.sort()
RGB_3.sort()
# 取出颜色中间值
RGB_1 = RGB_1[int(len(RGB_1) / 2)]
RGB_2 = RGB_2[int(len(RGB_2) / 2)]
RGB_3 = RGB_3[int(len(RGB_3) / 2)]
# 组成最可能的背景色
RGB_data = (RGB_1, RGB_2, RGB_3)
"""根据背景色选择文字颜色"""
if (RGB_1 * 0.299 + RGB_2 * 0.578 + RGB_3 * 0.114) >= 192: # 浅色
words_colour = (0, 0, 0) # 设置文字颜色为黑色
else:
words_colour = (255, 255, 255) # 设置文字颜色为白色
"""填充颜色"""
for x in range(0, width):
for y in range(0, height):
if (x >= lists[0] and y >= lists[1]) and (x <= lists[2] and y >= lists[3]) and (
x <= lists[4] and y <= lists[5]) and (x >= lists[6] and y <= lists[7]):
# pass
# 将该区域颜色改成背景色
img.putpixel((x, y), RGB_data)
"""填充文字"""
"""写字位置下调五分之一高度"""
add_low_size = int((lists[7] - lists[1]) * 1 / 5)
"""设置字体大小"""
#font_size=get_font_size(lists[7] - lists[1])
font_size = int(lists[7] - lists[1])
"""字体采用himalaya"""
font = ImageFont.truetype("C:\Windows\Fonts\himalaya.ttf", font_size)
# 画图
draw = ImageDraw.Draw(img)
draw.text((lists[0], lists[1] + add_low_size), words, words_colour, font=font) # 设置文字位置/内容/颜色/字体
draw = ImageDraw.Draw(img)
# 另存图片
img.save("C:/Users/Administrator/Desktop/new_test.png") # 保存图片
print("图片保存完成")
;
;
;
其中调用第三方API翻译接口的Demo我也贴在下面,因为是用的公司账号,所以省略掉密钥,你们需要就自己注册:
import sys
import uuid
import requests
import hashlib
import time
YOUDAO_URL = 'http://openapi.youdao.com/api'
APP_KEY = '*************'
APP_SECRET = '**************************'
def encrypt(signStr):
hash_algorithm = hashlib.sha256()
hash_algorithm.update(signStr.encode('utf-8'))
return hash_algorithm.hexdigest()
def truncate(q):
if q is None:
return None
size = len(q)
return q if size <= 20 else q[0:10] + str(size) + q[size - 10:size]
def do_request(data):
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
return requests.post(YOUDAO_URL, data=data, headers=headers)
def connect_translate(q):
#q = "我想知道,你在干什么"
data = {}
data['from'] = 'zh-CHS'
data['to'] = 'EN'
data['signType'] = 'v3'
curtime = str(int(time.time()))
data['curtime'] = curtime
salt = str(uuid.uuid1())
signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET
sign = encrypt(signStr)
data['appKey'] = APP_KEY
data['q'] = q
data['salt'] = salt
data['sign'] = sign
response = do_request(data)
if response.status_code!=200:
print("接口调用异常,code!=200")
return False
result=response.json()
if result.get('errorCode')!="0":
print("接口调用异常,errorCode!=0")
return False
print(result)
translation_list=result.get('translation')
if translation_list:
if len(translation_list)==1:
translation=translation_list[0]
else:
translation=','.join(translation_list)
return translation
else:
print("接口返回异常,translation:%s"%translation_list)
return False
if __name__ == '__main__':
s=connect_translate("你在干什么呢")
print(s)
;
;
;
关于调用网易智云识别文字内容的Demo,我也贴在下面:
# 获取图片识别后的汉字坐标——json
import os
import uuid
import requests
import base64
import hashlib
import time
YOUDAO_URL = "https://openapi.youdao.com/ocrapi"
APP_KEY = '***********'
APP_SECRET = '***************'
def truncate(q):
q=str(q, encoding='utf-8')
if q is None:
return None
size = len(q)
return q if size <= 20 else q[0:10] + str(size) + q[size - 10:size]
def encrypt(signStr):
hash_algorithm = hashlib.sha256()
hash_algorithm.update(signStr.encode('utf-8'))
return hash_algorithm.hexdigest()
def do_request(data):
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
return requests.post(YOUDAO_URL, data=data, headers=headers)
def connect(path,filename):
# 以url形式打开图片
# img_src = "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1559215600107&di=b28d63c9278b79da126a1ba8d02b128f&imgtype=0&src=http%3A%2F%2Fphotocdn.sohu.com%2F20151020%2FImg423681277.jpg"
# response=requests.get(img_src)
# q = base64.b64encode(response.content)
# 拼接完整链接
path=os.path.join(path, filename)
print(path)
# 本地打开图片
f = open(path, 'rb') # 二进制方式打开图文件
q = base64.b64encode(f.read()) # 读取文件内容,转换为base64编码,返回类型为bytes
f.close()
data = {}
data['detectType'] = '10012' # 识别类型,按行识别
data['imageType'] = '1' # 图片类型,目前只支持Base64
data['langType'] = 'zh-CHS' # 要识别的语言类型
data['img'] = q # 要识别的图片,需要Base64编码
data['docType'] = 'json' # 服务器响应类型,目前只支持json
data['signType'] = 'v3' # 签名类型
curtime = str(int(time.time())) # 当前UTC时间戳
data['curtime'] = curtime
data['column']='columns' # 是否按多列识别:onecolumn:按单列识别;columns:按多列识别
salt = str(uuid.uuid1())
signStr = APP_KEY + truncate(q) + salt + curtime + APP_SECRET
sign = encrypt(signStr)
data['appKey'] = APP_KEY
data['salt'] = salt
data['sign'] = sign
response = do_request(data)
print (response.json())
return response.json()
if __name__ == '__main__':
path=r'C:/Users/Administrator/Desktop/AIphoto/photo_test'
filename='1027.jpg'
print(connect(path,filename))