def write_main_text(img: Image.Image, text: str, font: ImageFont.ImageFont, end_y_heading: int, line_spacing: int) -> None: """Inserts the undertitles into the image. Args: img (Image.Image): The image into which undertitles will be inserted. text (str): The text to be inserted. font (ImageFont.ImageFont): The font used for the inserted text. end_y_heading (int): The lowest y of the heading. line_spacing (int, optional): Spacing between lines. Defaults to 30. Returns: Image.Image: The image into which undertitles are inserted. """ img_width, img_height = img.size draw = ImageDraw.Draw(img) # start_y = end_y_heading + line_spacing # TODO hier start y einsetzen start_y = calc_start_y_undertitles(img, text, font, end_y_heading, line_spacing, None) + end_y_heading font_width, font_height = font.getsize(text) pattern = pattern_2nd_text(text, img_width, font) for vert_start, line in pattern: draw_pos = (vert_start, start_y) draw.text(draw_pos, line, (0, ) * 3, font) start_y += font_height + line_spacing
def wrap_font_text(font: ImageFont.ImageFont, text: str, max_width: int) -> str: wrapper = TextWrapper() chunks = wrapper._split_chunks(text) lines: List[List[str]] = [] cur_line: List[str] = [] cur_line_width = 0 for chunk in chunks: width, _ = font.getsize(chunk) # If this chunk makes our line too long... if cur_line_width + width > max_width: # Special case: a single chunk that's too long to fit on one line. # In that case just use that chunk as a line by itself, otherwise # we'll enter an infinate loop here. if cur_line_width == 0: lines.append([chunk]) cur_line = [] cur_line_width = 0 continue lines.append(cur_line) cur_line = [] if chunk.isspace() else [chunk] cur_line_width = width else: cur_line.append(chunk) cur_line_width += width lines.append(cur_line) return "\n".join("".join(line).strip() for line in lines).strip()
def write_header(img: Image.Image, text: str, font: ImageFont.ImageFont, height_map_part: int, frame_width: int, adjustment: int = -150) -> int: """Inserts the header into the image. Args: img (Image.Image): The image where the header will be inserted. text (str): The text to be inserted. font (ImageFont.ImageFont): The font used for the heading. height_map_part (int): The height of the raw map. frame_width (int): The width of the frame. adjustment (int, optional): Adjustment to the height. Defaults to -150. Returns: int: The lowest y position to which the heading reaches. """ draw = ImageDraw.Draw(img) start_y_heading = height_map_part + frame_width + adjustment draw.text((0, start_y_heading), text, 'black', font) _, heading_height = font.getsize(text) end_y_heading = start_y_heading + heading_height return end_y_heading
def draw_text(image: Image.Image, text: str, text_color: tuple, font: ImageFont.ImageFont = None) -> Image: if font is None and os.path.isfile(FONT_DEFAULT): font = FONT_DEFAULT font_size = int(image.width * 0.07) font = ImageFont.truetype(font=font, size=font_size) text_width, text_height = font.getsize(text) text_position = ((image.width - text_width) / 2, (image.height - text_height) / 2) drw = ImageDraw.Draw(image, "RGBA") drw.multiline_text(text_position, text, fill=text_color, font=font) return image
def draw_text_relative(draw: ImageDraw.ImageDraw, anchor: Tuple[float, float], text: str, font: ImageFont.ImageFont, xa: float = 0, ya: float = 0, clamp_image: Image.Image = None): x, y = anchor w, h = font.getsize(text) x -= w * xa y -= h * ya if clamp_image is not None: x = max((0, min((clamp_image.width - w, x)))) y = max((0, min((clamp_image.height - h, y)))) draw.text((x, y), text, font=font)
def main(stream_url, image_path, location): print(stream_url, image_path, location) cfg = ConfigParser() cfg.read(str(CFG_PATH)) token, chat_id = cfg['tg']['token'], cfg['tg']['chat_id'] password, water = cfg['enc']['password'], cfg['enc']['water'] ip = IP_RE.findall(stream_url)[0] water = '%s %s' % (eip4(ip), water) url = 'https://api.telegram.org/bot%s/sendphoto' % token data = dict(chat_id=chat_id, caption='```%s```' % stream_url, parse_mode='Markdown') with open(image_path, 'rb') as f: img: Image = Image.open(f) w, h = img.size text = ' '.join(location) print(w, h) font_size = int(0.04 * min(h, w)) px = int(0.005 * w) py = int(0.002 * h) font = ImageFont.truetype(str(FONT_PATH), font_size) draw = ImageDraw.Draw(img, 'RGBA') _, text_height = draw.textsize('Wg', font) water_width, _ = draw.textsize(water, font) text_y = h - py - text_height draw.rectangle((0, text_y - py, w, h), fill=(0, 0, 0, 160)) draw.text((px, text_y), text, fill='yellow', font=font) draw.text((w - px - water_width, text_y), water, fill=(255, 255, 255, 128), font=font) img_byte_arr = io.BytesIO() img.save(img_byte_arr, format='PNG') img_byte_arr = img_byte_arr.getvalue() response = requests.post(url, data=data, files={'photo': img_byte_arr}) print(response.json())
def calc_start_y_undertitles(img: Image.Image, undertitles_text: str, undertitles_font: ImageFont.ImageFont, end_y_heading: int, line_spacing: int, town_names: Union[None, List[str]]) -> int: """Calculates where to put the undertitles. Args: img (Image.Image): The image into which the undertitles will be put. undertitles_text (str): The undertitle as string. undertitles_font (ImageFont.ImageFont): The font of the undertitles. end_y_heading (int): The lowest y position of the heading. line_spacing (int): The spacing between the lines of the undertitles. town_names (Union[None, List[str]]): The names of possible towns. Returns: int: The y position at which the undertitles to start. """ img_width, img_height = img.size empty_height = img_height - end_y_heading coats_wanted = town_names is not None if coats_wanted: pattern = pattern_2nd_text_with_coats(undertitles_text, img, undertitles_font, line_spacing, town_names) lines = [compile_to_line(line) for _, line, _ in pattern] else: pattern = pattern_2nd_text(undertitles_text, img.width, undertitles_font, line_dist=line_spacing) lines = [line for _, line in pattern] num_lines = len(lines) num_gaps = num_lines - 1 _, line_height = undertitles_font.getsize('Tg') undertitles_height = line_height * num_lines + line_spacing * num_gaps # assert empty_height > undertitles_height diff = empty_height - undertitles_height return round(diff / 2)
def get_code(request): mode = 'RGD' size = (200, 100) def _get_color(): return random.randrange(255) def _generate_code(): source = 'asdjcfboiawuehrbgtfoui21345asdcasdc' code = '' for i in range(4): code += random.choice(source) return code red = _get_color() green = _get_color() blue = _get_color() color_bg = (red, green, blue) image = Image.new(mode=mode, size=size, color=color_bg) image_draw = ImageDraw(image, mode=mode) image_font = ImageFont.truetype(settings.FONT_PATH, 100) verify_code = _generate_code() request.session['verify_code'] = verify_code for i in range(len(verify_code)): image_draw.text(xy=(40 * i, 0), text=verify_code[i], font=image_font) for i in range(1000): fill = (_get_color(), _get_color(), _get_color()) xy = (random.randrange(201), random.randrange(100)) image_draw.point(xy=xy, fill=fill) fp = BytesIO() image.save(fp, 'png') return HttpResponse(fp.getvalue(), content_type='img/png')
def rainbow_multiline_text(self, xy: tuple, text: str, fill: list = None, randomise: bool = False, font: ImageFont.ImageFont = None, spacing: int = 4, align: str = "left", alignY: str = "top", text_align: str = "left", stroke_width: int = 0, stroke_fill: tuple = None, embedded_color: bool = None): """ Draws a string of text at the defined position but uses different colours for each letter. :param xy: tuple :param text: str :param fill: list :param randomise bool :param font: PIL.ImageFont.ImageFont :param spacing: int (The number of pixels between lines. (default 4)) :param align: str (Determines the relative alignment of the text based off of the x co-ord. (this is slightly different to vanilla PIL as anchors are not used in this)) :param alignY: str (Determines the relative alignment of the text based off of the y co-ord. (this is slightly different to vanilla PIL as anchors are not used in this)) :param text_align: str (Sets the text align based on its position. (This is similar to align in vanilla PIL except it stays in the same xy position)) :param stroke_width: int (The width of the text stroke.) :param stroke_fill: tuple (Color to use for the text stroke. (if none parsed will use the defined colours)) :param embedded_color: bool (Whether to use font embedded color glyphs. (COLR or CBDT)) """ if embedded_color and self.image.mode not in ("RGB", "RGBA"): raise ValueError( "Embedded color supported only in RGB and RGBA modes") if not font: font = ImageDraw.Draw(self.image).getfont() x, y = xy lines = core.multiline_split(text) draw = ImageDraw.Draw(self.image) current = 0 render_size = font.getsize_multiline(text, spacing=spacing) if fill is None: fill = RAINBOW_DEFAULT def next_colour(n): n += 1 return 0 if n == len(fill) else n if align != "left": x -= render_size[0] if align == "right" else 0 x -= int(render_size[0] / 2) if align == "center" else 0 if alignY != "top": y -= render_size[1] if alignY == "bottom" else 0 y -= int(render_size[1] / 2) if alignY == "center" else 0 for line in lines: lineX = x if text_align != "left": lineX += render_size[0] - font.getsize( line)[0] if text_align == "right" else 0 lineX += int((render_size[0] - font.getsize(line)[0]) / 2) if text_align == "center" else 0 for letter in list(line): draw.text((lineX, y), letter, font=font, fill=choice(fill) if randomise else fill[current], stroke_width=stroke_width, stroke_fill=stroke_fill, embedded_color=embedded_color) lineX += font.getsize(letter)[0] current = next_colour(current) y += font.getsize(line)[1] + spacing
def rainbow_text(self, xy: tuple, text: str, fill: list = None, randomise: bool = False, font: ImageFont.ImageFont = None, align: str = "left", alignY: str = "top", stroke_width: int = 0, stroke_fill: tuple = None, embedded_color: bool = None): """ Draws a string of text at the defined position but uses different colours for each letter. :param xy: tuple :param text: str :param fill: list :param randomise bool :param font: PIL.ImageFont.ImageFont :param align: str :param alignY: str :param stroke_width: int :param stroke_fill: tuple :param embedded_color: bool """ if core.multiline_check(text): return self.rainbow_multiline_text(xy=xy, text=text, fill=fill, randomise=randomise, font=font, align=align, alignY=alignY, stroke_width=stroke_width, stroke_fill=stroke_fill, embedded_color=embedded_color) if embedded_color and self.image.mode not in ("RGB", "RGBA"): raise ValueError( "Embedded color supported only in RGB and RGBA modes") if not font: font = ImageDraw.Draw(self.image).getfont() x, y = xy if fill is None: fill = RAINBOW_DEFAULT draw = ImageDraw.Draw(self.image) render_size = font.getsize(text) if align != "left": x -= render_size[0] if align == "right" else 0 x -= int(render_size[0] / 2) if align == "center" else 0 if alignY != "top": y -= render_size[1] if alignY == "bottom" else 0 y -= int(render_size[1] / 2) if alignY == "center" else 0 current = 0 for letter in list(text): draw.text((x, y), letter, font=font, fill=choice(fill) if randomise else fill[current], stroke_width=stroke_width, stroke_fill=stroke_fill, embedded_color=embedded_color) x += font.getsize(letter)[0] current += 1 current = 0 if current == len(fill) else current
def _create_image_for_pair(rows, model_m, pair): length = len(rows) if length > 10: return w, h = 480, 480 distance = 30 interval = int((w - distance) / (length + 3)) # Интервал между стрелок if abs(float(rows[0][1])) > abs(float(rows[length - 1][1])): max = float(rows[0][1]) else: max = float(rows[length - 1][1]) min_value = str(round(rows[-1][1], 2)) h_scale = h - 80 # ДЛя графиков чтобы оставить место подписи for row in rows: if (max < 0 and float(row[1]) > 0): row[1] = int((float(row[1])) * (h_scale / 2 - 10) / max * (-1)) elif (max < 0 and float(row[1]) < 0): row[1] = int((float(row[1])) * (h_scale / 2 - 10) / max * (-1)) else: row[1] = int((float(row[1])) * (h_scale / 2 - 10) / max) im = Image.new('RGB', (w, h), (195, 197, 200)) na = np.array(im) h_begin = int(h_scale / 2) # Оси na = cv2.arrowedLine(na, (3, h_begin), (w - 5, h_begin), (0, 0, 0), 4) na = cv2.arrowedLine(na, (distance, h - 50), (distance, 5), (0, 0, 0), 4) h_end = int(h_scale / 2 - (rows[-1][1])) na = cv2.line(na, (15, h_end), (45, h_end), (0, 0, 0), 4) distance += interval * 2 for row in rows: h_end = int(h_scale / 2 - (row[1])) na = cv2.arrowedLine(na, (distance, h_begin), (distance, h_end), (0, 0, 0), 4) distance += interval path = f'{MEDIA_ROOT}/files/models/{str(model_m.model.id)}/original_snod/modification/{str(model_m.id)}/images/{str(pair.id)}.png' Image.fromarray(na).save(path) # Делаем подписи img = Image.open(path) idraw = ImageDraw.Draw(img) path_font = f'{MEDIA_ROOT}/fonts/9041.ttf' font = ImageFont.truetype(path_font, size=18) distance = 30 distance += interval * 2 for row in rows: text = str((row[0]) + 1) if float(row[1]) > 0: idraw.text((distance, int(h_scale / 2 + 50)), text, font=font, fill='#000000') elif float(row[1]) == 0: idraw.ellipse( [distance - 10, h_begin - 10, distance + 10, h_begin + 10], fill='#000000') idraw.text((distance, int(h_scale / 2 - 50)), text, font=font, fill='#000000') else: idraw.text((distance, int(h_scale / 2 - 50)), text, font=font, fill='#000000') distance += interval text = pair.option_1.name length = len(text) * 9 idraw.text((w - 15 - length, h - 40), pair.option_2.name, font=font, fill='#000000') idraw.text((15, h - 40), text, font=font, fill='#000000') idraw.text((w - 45, h / 2), 'Ox', font=font, fill='#000000') idraw.text((60, 15), 'Oy', font=font, fill='#000000') # Подписываем риски h_end = int(h_scale / 2 - (rows[-1][1])) idraw.text((45, h_end), min_value, font=font, fill='#000000') img.save(path)
def write_main_text_with_heraldry( img: Image.Image, text: str, font: ImageFont.ImageFont, line_spacing: int, town_names: List[str], end_y_heading: int, # The y position at which the heading ends. coat_text_gap: int = 15) -> None: """Inserts the undertitles into the image uncluding heraldry. Args: img (Image.Image): The image into which undertitles will be inserted. text (str): The text to be inserted. font (ImageFont.ImageFont): The font used for the inserted text. line_spacing (int): Spacing between lines. town_names (List[str]): The town names for which coats are provided. end_y_heading (int): The lowest y position of the heading. """ _, font_height = font.getsize('Tg') # start_y = end_y_heading + line_spacing TODO hier start_y einsetzen start_y = calc_start_y_undertitles(img, text, font, end_y_heading, line_spacing, town_names) + end_y_heading complete_text_pattern = pattern_2nd_text_with_coats( text, img, font, line_spacing, town_names) added_width_of_line_by_coat = [] for _, line_pattern, _ in complete_text_pattern: line = compile_to_line(line_pattern) added_width_in_this_line = 0 for line_element in line: if type(line_element) is not str: element_width, _ = proportional_size(font_height, line_element) added_width_in_this_line += element_width + 2 * coat_text_gap added_width_of_line_by_coat.append(added_width_in_this_line) for iter_num, (start_x, line_pattern, num_coats) in enumerate(complete_text_pattern): added_coat_width = added_width_of_line_by_coat[iter_num] print(max(added_width_of_line_by_coat) - added_coat_width) start_x += round( (max(added_width_of_line_by_coat) - added_coat_width) / 2) line = compile_to_line(line_pattern) drawing = ImageDraw.Draw(img) for i, line_element in enumerate(line): if type(line_element) is str: drawing.text((start_x, start_y), line_element, font=font, fill='black') element_width, _ = font.getsize(line_element) start_x += element_width else: start_x += coat_text_gap if not i == 0 else 0 element_width, element_height = proportional_size( font_height, line_element) line_element.thumbnail((element_width, element_height)) img.paste(line_element, (start_x, start_y), line_element) start_x += element_width + coat_text_gap start_y += font_height + line_spacing
#coding=utf-8 from PIL.ImageFont import ImageFont from gevent.libev.corecext import sys import HyperLPRLite as pr import cv2 import numpy as np import imp imp.reload(sys) fontC = ImageFont.truetype("Font/platech.ttf", 14, 0) # 从本地读取图片并做识别,返回所有识别到车牌的【识别结果,置信度,位置】 # smallest_confidence:最小置信度 def recognize_plate(image, smallest_confidence = 0.7): model = pr.LPR("model/cascade.xml", "model/model12.h5", "model/ocr_plate_all_gru.h5") #训练好的模型参数 model.SimpleRecognizePlateByE2E(image) return_all_plate = [] for pstr,confidence,rect in model.SimpleRecognizePlateByE2E(image): if confidence>smallest_confidence: return_all_plate.append([pstr,confidence,rect]) #返回车牌号,车牌位置,置信度 return return_all_plate test_image = cv2.imread("Images/16.jpg") #读入图片 print(recognize_plate(test_image)) #打印结果,车牌号,车牌位置,置信度