環境:python3.6
本篇文章主要講述的功能是如何把一張包含中文文字的圖片轉換成英文圖片,並且保證圖片不受影響。
這裏先舉個案例:
上圖的左邊是原始圖片沒有做任何處理,右邊是經過代碼處理過翻譯後的圖片,(由於截圖原因導致兩張圖大小與實際有點偏差)
首先我們先講一下這個項目的大致思路:
1.識別出圖片中全部文字的座標。
這一點我是藉助有道智雲的ocr圖片識別接口獲取座標信息的
詳情自己去看,他們有文檔,註冊送100元試用,能用很久,鏈接:有道智雲服務地址。
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))