PIL画图
功能
- 画带透明度的圆,调整透明度
- 画虚线
- 画直线,直线没有锯齿
from PIL import Image, ImageDraw
import aggdraw
import time
import cv2
import numpy as np
TRANSPARENT_RED_COLOR = (255, 114, 114, 80)
TRANSPARENT_WHITE_COLOR = (255, 255, 255, 80)
RED_COLOR = (255, 114, 114)
WHITE_COLOR = (255, 255, 255)
KEYPOINT_EDGE = [(3, 4),(5, 7),(7, 9),(6, 8),(8, 10),(5, 6),(5, 11),(6, 12),(11, 12),(11, 13),(13, 15),(12, 14),(14, 16)]
KEYPOINT_EDGE_SIDE = [
(4, 6),(6, 12),(12, 14),(14, 16)
]
POSTURE_POINTS = {
"head_tilt": [3,4],
"uneven_shoulders": [5,6],
"scoliosis": [5,6,11,12],
"X_legs": [11,12,13,14,15,16],
"O_legs": [11,12,13,14,15,16],
"neck_tilt": [4,6],
"hunchback": [4,6,12],
}
POSTURE_LINES = {
"head_tilt": [[3, 4]],
"uneven_shoulders": [[5, 6]],
"scoliosis": [[5, 6],[11, 12],[5, 11],[6, 12]],
"X_legs": [[11,13],[13,15]],
"O_legs": [[12,14],[14,16]],
"neck_tilt": [[4, 6]],
"hunchback": [[4, 6],[6,12]],
}
side_postures = ['neck_tilt', 'hunchback']
front_postures = ['head_tilt', 'uneven_shoulders', 'scoliosis', 'X_legs', 'O_legs']
def draw_dash_line(draw,start_point,end_point,line_width,line_color):
dash_length = 8
gap_length = 5
total_length = ((end_point[0] - start_point[0]) ** 2 + (end_point[1] - start_point[1]) ** 2) ** 0.5
dx = (end_point[0] - start_point[0]) / total_length
dy = (end_point[1] - start_point[1]) / total_length
current_length = 0
while current_length < total_length:
segment_start = (
int(start_point[0] + current_length * dx),
int(start_point[1] + current_length * dy)
)
segment_end = (
int(start_point[0] + (current_length + dash_length) * dx),
int(start_point[1] + (current_length + dash_length) * dy)
)
draw.line([segment_start, segment_end], fill=line_color, width=line_width)
current_length += dash_length + gap_length
return draw
def draw_circel(draw,circle_center,circle_radius,circle_color):
draw.ellipse([circle_center[0] - circle_radius, circle_center[1] - circle_radius,
circle_center[0] + circle_radius, circle_center[1] + circle_radius],
fill=circle_color, outline=None, width=2)
return draw
def draw_line(draw,start_point,end_point,line_color,line_width,is_dash=False):
start_point = (int(start_point[0]),int(start_point[1]))
end_point = (int(end_point[0]),int(end_point[1]))
if is_dash:
draw.line([start_point, end_point], fill=line_color, width=line_width, joint='curve')
else:
pen = aggdraw.Pen(line_color, width=line_width)
draw.line([start_point[0],start_point[1], end_point[0],end_point[1]], pen)
return draw
def draw_front_image(image,kpts,posture_results):
abnormal_type = []
abnormal_points = []
abnormal_lines = []
for k in front_postures:
pos_res = posture_results[k]
if pos_res:
abnormal_type.append(k)
for posture in abnormal_type:
points = POSTURE_POINTS[posture]
lines = POSTURE_LINES[posture]
abnormal_points.extend(points)
for line in lines:
if line not in abnormal_lines:
abnormal_lines.append(line)
abnormal_points = set(abnormal_points)
img_shape = image.shape
radius = max(4, int(max(img_shape) / 250))
transparent_circle_radius = radius * 2 + 2
image = Image.fromarray(image).convert("RGBA")
overlay = Image.new('RGBA', image.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(overlay)
for idx, landmark in enumerate(kpts[3:]):
circle_center = list(map(int, landmark))
draw_circel(draw, circle_center, transparent_circle_radius, TRANSPARENT_WHITE_COLOR)
for idx in abnormal_points:
landmark = kpts[idx]
circle_center = list(map(int, landmark))
draw_circel(draw, circle_center, transparent_circle_radius, TRANSPARENT_RED_COLOR)
for i in [4, 6, 12, 14, 16]:
y = int(kpts[i][1])
start_point = [0, y]
end_point = [img_shape[1], y]
draw_dash_line(draw, start_point, end_point, line_width=max(radius - 4, 2),
line_color=TRANSPARENT_WHITE_COLOR)
result = Image.alpha_composite(image, overlay)
draw = ImageDraw.Draw(result)
for idx, landmark in enumerate(kpts[3:]):
circle_center = list(map(int, landmark))
draw_circel(draw, circle_center, radius, WHITE_COLOR)
for idx in abnormal_points:
landmark = kpts[idx]
circle_center = list(map(int, landmark))
draw_circel(draw, circle_center, radius, RED_COLOR)
draw = aggdraw.Draw(result)
for line_pairs in KEYPOINT_EDGE:
start_point = kpts[line_pairs[0]]
end_point = kpts[line_pairs[1]]
draw = draw_line(draw, start_point, end_point, line_color=WHITE_COLOR,
line_width=max(radius - 4, 2), is_dash=False)
for line_pairs in abnormal_lines:
start_point = kpts[line_pairs[0]]
end_point = kpts[line_pairs[1]]
draw = draw_line(draw, start_point, end_point, line_color=RED_COLOR, line_width=max(radius - 4, 2),
is_dash=False)
draw.flush()
img = cv2.cvtColor(np.asarray(result), cv2.COLOR_RGBA2BGR)
return img
def draw_side_image(image,kpts,posture_results):
abnormal_type = []
abnormal_points = []
abnormal_lines = []
for k in side_postures:
pos_res = posture_results[k]
if pos_res:
abnormal_type.append(k)
for posture in abnormal_type:
points = POSTURE_POINTS[posture]
lines = POSTURE_LINES[posture]
abnormal_points.extend(points)
for line in lines:
if line not in abnormal_lines:
abnormal_lines.append(line)
abnormal_points = set(abnormal_points)
img_shape = image.shape
radius = max(4, int(max(img_shape) / 250))
transparent_circle_radius = radius * 2 + 2
image = Image.fromarray(image).convert("RGBA")
overlay = Image.new('RGBA', image.size, (0, 0, 0, 0))
draw = ImageDraw.Draw(overlay)
for idx, landmark in enumerate(kpts):
if idx not in [4,6,12,14,16]:
continue
circle_center = list(map(int, landmark))
draw_circel(draw, circle_center, transparent_circle_radius, TRANSPARENT_WHITE_COLOR)
for idx in abnormal_points:
landmark = kpts[idx]
circle_center = list(map(int, landmark))
draw_circel(draw, circle_center, transparent_circle_radius, TRANSPARENT_RED_COLOR)
idx = 16
x = int(kpts[idx][0])
start_point = [x,0 ]
end_point = [x, img_shape[0]]
draw_dash_line(draw, start_point, end_point, line_width=max(radius - 4, 2),
line_color=TRANSPARENT_WHITE_COLOR)
result = Image.alpha_composite(image, overlay)
draw = ImageDraw.Draw(result)
for idx, landmark in enumerate(kpts):
if idx not in [4,6,12,14,16]:
continue
circle_center = list(map(int, landmark))
draw_circel(draw, circle_center, radius, WHITE_COLOR)
for idx in abnormal_points:
landmark = kpts[idx]
circle_center = list(map(int, landmark))
draw_circel(draw, circle_center, radius, RED_COLOR)
draw = aggdraw.Draw(result)
for line_pairs in KEYPOINT_EDGE_SIDE:
start_point = kpts[line_pairs[0]]
end_point = kpts[line_pairs[1]]
draw = draw_line(draw, start_point, end_point, line_color=WHITE_COLOR,
line_width=max(radius - 4, 2), is_dash=False)
for line_pairs in abnormal_lines:
start_point = kpts[line_pairs[0]]
end_point = kpts[line_pairs[1]]
draw = draw_line(draw, start_point, end_point, line_color=RED_COLOR, line_width=max(radius - 4, 2),
is_dash=False)
draw.flush()
img = cv2.cvtColor(np.asarray(result), cv2.COLOR_RGBA2BGR)
return img