-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmark.py
243 lines (226 loc) · 7.25 KB
/
mark.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# !/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@contact: [email protected]
@file: mark_image.py
@time: 2023/01/14/ 20:58
@desc:不上传可以不导入这个from Project.util import bos_util,这是基于bos封装的自定义工具包,会报错,相关代码删掉就行
"""
import os
import json
from PIL import ImageFont, Image, ImageDraw
import cv2 as cv
import numpy as np
# from Project.util import bos_util
class MarkImage():
def __init__(self):
self.bos_client = bos_util.get_bos_client()
# 是否标注文字
self.TEXT = True
# 是否标注方框
self.BOX = True
# 是否标注文字索引
self.INDEX = True
# 标注文字大小
self.SIZE = 20
# 是否旋转
self.TRANSPOSE = False
# 标注字体格式
self.Font = R'C:\\Windows\\Fonts\\simkai.ttf'
# 标注颜色
self.COLOR = (0, 0, 255)
# 标注线粗
self.THICKNESS = 2
# bos路径唯一标识符
self.SINGLE = "MarkImage"
# # 是否上传处理结果到bos
# self.UPLOAD = True
def save_log(self, file, text):
"""
保存日志
:param file:
:param text:
:return:
"""
with open(file, "a", encoding="utf-8")as fp:
fp.write("{}\n".format(text))
# def upload(self, file, retry=3):
# """
# 上传
# :param file:
# :param retry:
# :return:
# """
# source_bucket = 'collection-data'
# bos_file = "/jiaohaicheng/{}/{}".format(
# self.SINGLE, "/".join(file.split("\\")[-3:]))
# status = False
# while not status and retry > 0:
# try:
# if self.UPLOAD:
# bos_util.upload_file(
# self.bos_client, source_bucket, bos_file, file)
# status = True
# else:
# retry = 0
# except Exception as e:
# print(e,e.__traceback__.tb_lineno)
# retry -= 1
#
# if not status:
# if self.UPLOAD:
# return "Error Upload File : "+"https://bj.bcebos.com/collection-data" + bos_file
# else:
# return file
# else:
# if self.UPLOAD:
# return "https://bj.bcebos.com/collection-data" + bos_file
def transpose(self, image, key: int):
"""
旋转,逆时针
"""
return image.rotate(key)
def read_image(self, file, key=0):
"""
读取图像,带旋转功能
:param file:
:param key:
:return:
"""
img = Image.open(file).convert('RGB')
if self.TRANSPOSE:
img = self.transpose(img, key)
img = np.asarray(img)
return img
def save_img(self, img, file, name=".jpg"):
"""
保存图像到本地
:param img:
:param file:
:param name:
:return:
"""
cv.imencode(name, img)[1].tofile(file)
def draw_polygon(self, img, opt_lis):
"""
标注框
:param img:图像 numpy
:param opt_lis: 标注位置坐标
:return:
"""
if self.BOX:
if len(opt_lis) != 2:
pts = np.array(opt_lis, dtype=np.int32)
cv.polylines(img,
[pts],
True,
self.COLOR,
self.THICKNESS
)
else:
cv.rectangle(
img,
tuple(opt_lis[0]),
tuple(opt_lis[1]),
color=self.COLOR,
thickness=self.THICKNESS
)
def calculate_max_opt(self, opt):
"""
计算最大横纵坐标,横坐标加上偏移量(字体大小的1/5)
:param opt: [[,],[,]]
:return:
"""
max_x = []
max_y = []
for i in opt:
if len(i) == 2:
max_x.append(i[0])
max_y.append(i[1])
return max(max_x) + self.SIZE / 5, max(max_y) - self.SIZE / 5
def add_words_on_pic(self, opt, index, text, image):
"""
添加文字
:param opt: tuple (,)
:param index: 标注文本序号
:param text: 标注文本
:param image: 图像 ,numpy
:return:
"""
_text = ""
if self.INDEX:
_text = str(index)
if self.TEXT:
_text = _text + "." + text
else:
if self.TEXT:
_text = text
try:
font = ImageFont.truetype(self.Font, size=self.SIZE)
img_PIL = Image.fromarray(image)
draw = ImageDraw.Draw(img_PIL)
draw.text(xy=(opt[0], opt[1] - (self.SIZE / 2)),
text=_text, font=font, fill=(0, 0, 255))
image = cv.cvtColor(np.asarray(img_PIL), cv.COLOR_RGB2RGBA)
except Exception as e:
print("add_words_on_pic error", e, e.__traceback__.tb_lineno)
return image
def process(self, file, map_lis, save_file):
"""
图像处理流程
:param file:图像位置
:param map_lis: 标注坐标[1:{opt:value}]
:param id: 标注文本序号
:param text: 标注文本
:param save_file: 图像存储位置
:return:
"""
try:
# 读取图像
img = self.read_image(file)
for index,value in map_lis.items():
# 标注框
self.draw_polygon(img, value["opt"])
# 计算文本标注位置(x最大值+偏移量,y最大值-偏移量)
opt = self.calculate_max_opt(value["opt"])
# 标注文字
img = self.add_words_on_pic(opt=opt, index=index, text=value["text"], image=img)
# 保存图像
self.save_img(img, save_file)
# bos_file_status:上传状态,成功只返回bos路径,若失败,路径前有error upload file : 标识,未开启上传功能,返回本地待上传图片路径
bos_file_status = self.upload(save_file)
print(bos_file_status)
except Exception as e:
print("Process {} Error : ".format(file),e,e.__traceback__.tb_lineno)
# def get_info(self,file):
# with open(file,"r",encoding="utf-8")as fp:
# header = fp.readline()
# for i in fp:
if __name__ == '__main__':
mi = MarkImage()
file = R"E:\Desktop\20170427101835143.png"
save_path = R"F:\BaiduCodingSpace\SupportRequirements\Project\image\mark"
img_name = os.path.split(file)[-1]
os.makedirs(save_path, exist_ok=True)
save_file = os.path.join(save_path, img_name)
map_lis = {
1:{
"opt":[
[100, 200],
[130, 210],
[135, 282],
[100, 260],
],
"text":"中国"
},
2:{
"opt": [
[200, 200],
[230, 210],
[235, 282],
[200, 260],
],
"text":"日本"
}
}
mi.process(file, map_lis, save_file)