""" """ import cv2 import numpy as np from PIL import Image, ImageDraw, ImageFont from module.view_control.auto_deal_pics.data import DataModeAutoDealPics class OnePicDeal(object): def __init__(self): # 数据模型 self.data_mode_auto_deal_pics = DataModeAutoDealPics() def check_shoe_is_right(self, im=None, image_path=None): # 先进行API识别左右脚 if im is None: im = Image.open(image_path) try: r_data = self.data_mode_auto_deal_pics.check_is_right_foot_by_api(image=im) except BaseException as e: r_data = None print("20", e) flag = self.check_shoe_is_right_by_pixel(im=im) if r_data: if "拖鞋" in r_data: flag = flag is not True if flag: print("自动识别----->这是左脚") else: print("自动识别----->这是右脚") return flag def check_shoe_is_right_by_pixel(self, im=None, image_path=None): if im is None: im = Image.open(image_path) # 注意,只支持透明图 # 打开图像文件 im = im.crop(im.getbbox()) # image.show() # 获取图像第一行的像素数据 pixel_data = im.load() pix_list = [] h = int(im.height / 20) for i in range(im.width): _r, _g, _b, _a = pixel_data[i, h] if _a > 10: pix_list.append(i) left_f_num = 0 middle_w = int(im.width / 2) for i in pix_list: if i < middle_w: left_f_num += 1 else: left_f_num -= 1 if left_f_num > 0: return True else: return False def how_to_use(self): # 单图缩放处理 a = {"command": "resize", "plugins_mode": "relative", # pixel 相对(宽度、高度、其他参考图),或绝对像素 "base_im": {"im": "im"}, # 参考基于其他图 PIL格式 "base": "width", # base:pixel,width,height,by_im 基于长边、基于短边 (基于短边时,则缩放到指定尺寸)by_im确保能塞进参考图内 "value": 649, # 固定值,如果为百分比,则为0 "percentage": 0, } # 百分比 # 单图圆角处理 a = {"command": "radius", # radius "plugins_mode": "relative", # pixel 相对(短边),或绝对像素 "circular_pos": (0, 1, 0, 1), # 从左上角顺时针,记录圆角数量 "value": 649, # 固定值,如果为百分比,则为0 "percentage": 0, } # 百分比 # 单图处理成圆形 a = {"command": "circular", # circular } # 单图旋转处理 a = {"command": "rotate", "plugins_mode": "", "value": 649, # 固定值 顺时针 } # 图片粘贴处理 a = { "command": "paste_img", "img": {"im": "im"}, "pos": {"plugins_mode": "relative", # pixel "base": "center", # nw,nc,ne,ec ... 各个方向参考点 "value": (100, 100), "percentage": (0.5, 0.5), }, "margins": (0, 0, 0, 0), # 上下左右边距 } # 图片剪裁处理 a = { "command": "crop_img", "img": {"im": "im"}, "pos": {"plugins_mode": "relative", # pixel "base": "center", # nw,nc,ne,ec ... 各个方向参考点 "value": (100, 100, 10, 10), }, "color_fill": (255, 255, 255) } # 图片添加文字 a = { "command": "add_text", "pos": {"plugins_mode": "relative", # pixel "base": "center", # nw,nc,ne,ec ... 各个方向参考点 "value": (100, 100), "percentage": 0, }, "font": "", "text": "", "anchor": "", # mm 为居中 ma 为左右居中,上面居顶 "align": "对齐方式", "direction": "文本的方向", "max_len_one_line": "单行长度", "spacing": 10, "fill": "文字颜色", } def add_text(self, img: Image, command): draw_1 = ImageDraw.Draw(img) # 定义字体,你需要有一个.ttf字体文件 font = command["font"] text = command["text"] spacing = 4 if not command["spacing"] else command["spacing"] fill = command["fill"] anchor = None if not command["anchor"] else command["anchor"] align = "left" if not command["align"] else command["align"] # left, center 或 right _, _, text_width, text_height = draw_1.textbbox((0, 0), text, font=font) xy = (0, 0) if command["pos"]["plugins_mode"] == "pixel": value = command["pos"]["value"] xy = value draw_1.multiline_text(xy, text, fill=fill, font=font, anchor=anchor, spacing=spacing, align=align, direction=None, features=None, language=None, stroke_width=0, stroke_fill=None, embedded_color=False) return img def resize(self, img: Image, command): if command["plugins_mode"] == "pixel": if command["base"] == "width": img = self.to_resize(img, width=command["value"]) if command["base"] == "high": img = self.to_resize(img, height=command["value"]) # 相对值 if command["plugins_mode"] == "relative": base_im = command["base_im"]["im"] if command["base"] == "width": img = self.to_resize(img, width=img.width * command["percentage"] if not base_im else int( base_im.width * command["percentage"])) if command["base"] == "height": img = self.to_resize(img, width=img.height * command["percentage"] if not base_im else int( base_im.height * command["percentage"])) # by_im确保能塞进参考图内 if command["base"] == "by_im": percentage = 1 if not command["percentage"] else command["percentage"] box_width, box_height = int(base_im.width * percentage), int(base_im.height * percentage) width, height = img.width, img.height if box_width / box_height < width / height: scale = box_width / width else: scale = box_height / height img = img.resize((int(width * scale), int(height * scale))) # img.show() return img def paste_img(self, img: Image, command): # 粘贴绝对像素 base = "nw" if not command["pos"]["base"] else command["pos"]["base"] value = command["pos"]["value"] percentage = (0, 0) if not command["pos"]["percentage"] else command["pos"]["percentage"] if command["margins"]: top, down, left, right = command["margins"] else: top, down, left, right = 0, 0, 0, 0 if percentage != (0, 0): # percentage 不按占比模式 if base in ("nw", "wn", "wc", "cw", "nc", "cn", "center"): value = (int(img.width), int(img.height)) if base in ("sw", "ws", "sc", "cs", "center"): value = (int(img.width), -1 * int(img.height)) if base in ("ec", "ce"): value = (int(img.width), int(img.height)) img_1 = command["img"]["im"] if command["pos"]["plugins_mode"] == "pixel": if base == "ec" or "ce": p_x = int(img.width - img_1.width) + value[0] p_y = value[1] if base == "nw" or "wn": deviation_x, deviation_y = 0, 0 p_x, p_y = value if base == "cs" or "sc": p_x, p_y = value if base == "center": deviation_x, deviation_y = int((img.width - img_1.width) / 2), int((img.height - img_1.height) / 2) p_x = deviation_x + value[0] + left p_y = deviation_y + value[1] + top if base == "sw" or base == "ws": # deviation_x, deviation_y = 0, int((img.height - img_1.height)) p_x = value[0] + left p_y = img.height - (img_1.height + value[1] + down) if base == "wc" or base == "cw": p_x = value[0] + left p_y = int((img.height - img_1.height) / 2) + value[1] + top try: img.paste(img_1, (p_x, p_y), img_1) except: img.paste(img_1, (p_x, p_y), img_1.convert("RGBA")) return img def crop_img(self, img: Image, command): base = "nw" if not command["pos"]["base"] else command["pos"]["base"] # print(base) value = command["pos"]["value"] percentage = command["pos"]["percentage"] if command["margins"]: top, down, left, right = command["margins"] else: top, down, left, right = 0, 0, 0, 0 out_img_size = (value[2], value[3]) # 默认填充色 color_fill = command["color_fill"] if not color_fill: color_fill = (0, 0, 0) if command["pos"]["plugins_mode"] == "pixel": if base == "nw" or "wn": box = value if base == "sw" or base == "ws": # deviation_x, deviation_y = 0, int((img.height - img_1.height)) box = (value[0], img.height - (value[1] + value[3]), value[2], value[3]) print(box) if base == "se" or base == "es": box = (img.width - (value[0] + value[2]), img.height - (value[1] + value[3]), value[2], value[3]) print(box) box = [box[0], box[1], box[0] + box[2], box[1] + box[3]] print("box", box) print("img.width", img.width) print("img.height", img.height) out_img = img.crop(box=box) print(out_img.size) # out_img.show() if box[0] < 0: out_img.paste(Image.new("RGB", (-1 * box[0], out_img.height), color_fill), (0, 0)) # print(img.width, box) if box[2] > img.width: # print(box[2] - img.width, img.height) i = Image.new("RGB", (box[2] - img.width, out_img.height), color_fill) out_img.paste(i, (img.width - box[0], 0)) if box[1] < 0: out_img.paste(Image.new("RGB", (img.width, -1 * box[1]), color_fill), (0, 0)) if box[3] > img.height: out_img.paste(Image.new("RGB", (out_img.width, box[3] - img.height), color_fill), (0, img.height - box[1])) # bg_img = Image.new("RGB", out_img_size, color_fill) # if box[0] < 0: # x = -1 * box[0] # elif box[2] > img.width: # x = img.width - box[2] # else: # x = 0 # # if box[1] < 0: # y = -1 * box[1] # elif box[2] > img.height: # y = img.height - box[1] # else: # y = 0 # bg_img.paste(img, box=(x, y), ) # print(box) # img = img.crop(box=box) # out_img.show() return out_img def radius(self, img: Image, command): # 单图圆角处理 radii = command["value"] if radii > img.width / 2: radii = int(img.width / 2) if radii > img.height / 2: radii = int(img.height / 2) # 画圆(用于分离4个角) circle = Image.new('L', (radii * 2, radii * 2), 0) # 创建一个黑色背景的画布 draw = ImageDraw.Draw(circle) draw.ellipse((0, 0, radii * 2, radii * 2), fill=255) # 画白色圆形 # 原图 img = img.convert("RGBA") w, h = img.size # 画4个角(将整圆分离为4个部分) alpha = Image.new('L', img.size, 255) _pos = command["circular_pos"] if not _pos: _pos = (1, 1, 1, 1) for index, i in enumerate(_pos): if index == 0 and i == 1: alpha.paste(circle.crop((0, 0, radii, radii)), (0, 0)) # 左上角 if index == 1 and i == 1: alpha.paste(circle.crop((radii, 0, radii * 2, radii)), (w - radii, 0)) # 右上角 if index == 2 and i == 1: alpha.paste(circle.crop((radii, radii, radii * 2, radii * 2)), (w - radii, h - radii)) # 右下角 if index == 3 and i == 1: alpha.paste(circle.crop((0, radii, radii, radii * 2)), (0, h - radii)) # 左下角 # alpha.show() img.putalpha(alpha) # 白色区域透明可见,黑色区域不可见 return img def to_resize(self, _im, width=None, height=None): _im_x, _im_y = _im.size if width and height: if _im_x >= _im_y: height = None else: width = None if width: re_x = int(width) re_y = int(_im_y * re_x / _im_x) else: re_y = int(height) re_x = int(_im_x * re_y / _im_y) _im = _im.resize((re_x, re_y)) return _im def add_pic(self, detailed_images): if not detailed_images: return page_len = 0 for index, im in enumerate(detailed_images): page_len += im.height bg_im = Image.new("RGB", (im.width, page_len), (255, 255, 255)) n = 0 for index, im in enumerate(detailed_images): bg_im.paste(im, (0, n)) n += im.height # bg_im.show() return bg_im def get_goods_pos(self, im, cut_image): # 保留多余内容 old_x, old_y = im.size x1, y1, x2, y2 = cut_image.getbbox() goods_w, goods_h = x2 - x1, y2 - y1 _w, _h = int(goods_w / 10), int(goods_h / 10) # 上下左右扩展位置 new_x1, new_y1, new_x2, new_y2 = x1 - _w, y1 - _h, x2 + _w, y2 + _h # 防止超限 new_x1 = 0 if new_x1 < 0 else new_x1 new_y1 = 0 if new_y1 < 0 else new_y1 new_x2 = old_x if new_x2 > old_x else new_x2 new_y2 = old_y if new_y2 > old_y else new_y2 # 剪切掉多余的内容,保留阴影 im = im.crop((new_x1, new_y1, new_x2, new_y2)) # 切图 return im def deal_one_pic(self, data=None, is_show=False): """ 通用图片处理器 1、图片位置处理 输出拼接后的图片,以及拼接后商品所属位置 """ for command in data: if command["command"] == "paste_img": img1 = command["img1"]["im"] img2 = command["img2"]["im"] if "resize" in command["img2"]: if "width" in command["img2"]["resize"]: img2 = self.to_resize(img2, width=command["img2"]["resize"]["width"]) if is_show: img2.show() img1.paste(img2, command["img2"]["pos"]) if command["command"] == "image_crop": img1 = img1.crop(command["image_crop"]) img = img1 return img def deal_one_pic_2(self, orign_im, data=None): """ 通用图片处理器 1、基于某原始图,进行加工,包括粘贴、单图处理等逻辑 """ # 单图缩放处理 a = {"command": "resize", "plugins_mode": "relative", # pixel 相对(宽度、高度、其他参考图),或绝对像素 "base_im": "im", # 参考基于其他图 PIL格式 "base": "width", # base:pixel,width,height,by_long_side,by_short_side基于长边、基于短边 (基于短边时,则缩放到指定尺寸) "value": 649, # 固定值,如果为百分比,则为0 "percentage": 0, } # 百分比 # 单图圆角处理 a = {"command": "radius", # radius "plugins_mode": "relative", # pixel 相对(短边),或绝对像素 "circular_pos": (0, 1, 0, 1), # 从左上角顺时针,记录圆角数量 "value": 649, # 固定值,如果为百分比,则为0 "percentage": 0, } # 百分比 # 单图处理成圆形 a = {"command": "circular", # circular } # 单图旋转处理 a = {"command": "rotate", "plugins_mode": "", "value": 649, # 固定值 顺时针 } # 图片粘贴处理 a = { "command": "paste_img", "img": {"im": "im"}, "pos": {"plugins_mode": "relative", # pixel "base": "center", # nw,nc,ne,ec ... 各个方向参考点 "value": (100, 100), "percentage": 0, }, "margins": (0, 0, 0, 0), # 上下左右边距 } # 图片剪裁处理 a = { "command": "crop_img", "img": {"im": "im"}, "plugins_mode": "relative", # pixel "base": "center", # nw,nc,ne,ec ... 各个方向参考点 "box": (0, 0, 0, 0), } # 图片添加文字 a = { "command": "add_text", "pos": {"plugins_mode": "relative", # pixel "base": "center", # nw,nc,ne,ec ... 各个方向参考点 "value": (100, 100), "percentage": 0, }, "font": "", "text": "", "align": "对齐方式", "direction": "文本的方向", "fill": "文字颜色", } # 图片渐变处理 # https://blog.csdn.net/skying159/article/details/119532479 def get_value(data_dict, key): return 1 r_dict = {"nw": 0, } _r = 0 for command in data: if command["command"] == "paste_img": img1 = command["img1"]["im"] img2 = command["img2"]["im"] if "resize" in command["img2"]: if "width" in command["img2"]["resize"]: img2 = self.to_resize(img2, width=command["img2"]["resize"]["width"]) if "pos" in command["img2"]: base = command["img2"]["base"] value = command["img2"]["value"] if command["img2"]["plugins_mode"] == "relative": # 相对位置处理,居中比较特殊 # 其他的先进行旋转与镜像,处理后,进行反向操作 x, y = 0, 0 if base == "center": x, y = int((img1.width - img2.width) / 2), int((img1.height - img2.height) / 2) if base == "nw" or base == "nw": pass w, h = img1.width * value[0], img1.height * value[0] img1.paste(img2, command["img2"]["pos"]) if _r != 0: img1 = img1.rotate(_r * -1) continue if command["command"] == "image_crop": img1 = img1.crop(command["image_crop"]) continue img = img1 return img def get_overlay_pic(self, pil_img_1, pil_img_2, color): im_w, im_h = pil_img_1.size cv_im = cv2.cvtColor(np.asarray(pil_img_1), cv2.COLOR_RGB2BGR) # 创建一张纯色底图 image_white = Image.new("RGB", (im_w, im_h), color) cv_image_white = cv2.cvtColor(np.asarray(image_white), cv2.COLOR_RGB2BGR) new_im = self.to_color_2(cv_image_white, cv_im) # new_im = cv2.addWeighted(new_im, 0.7, cv_im_2, 0.3, 0) # new_im = cv2.add(new_im, cv_im_2) new_im = Image.fromarray(cv2.cvtColor(new_im, cv2.COLOR_BGR2RGB)) new_im.paste(pil_img_2, (0, 0), pil_img_2) return new_im def to_color_2(self, target, blend): # 正片叠底 return np.array(np.multiply(target / 256, blend / 256) * 256, dtype=np.uint8) def to_color_1(self, img1, img2): # PS颜色模式 img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV) img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2HSV) img2[:, :, 0] = img1[:, :, 0] img2[:, :, 1] = img1[:, :, 1] res = cv2.cvtColor(img2, cv2.COLOR_HSV2BGR) return res if __name__ == '__main__': from collections import defaultdict def set_dict(one_dict): _ = defaultdict(str) for i, v in one_dict.items(): if isinstance(v, dict): v = set_dict(v) _[i] = v return _ def deal_one_pic(img: Image, data=None): """ 通用图片处理器 1、基于某原始图,进行加工,包括粘贴、单图处理等逻辑 """ data = [set_dict(x) for x in data] for command in data: if command["command"] == "resize": img = OnePicDeal().resize(img, command) continue if command["command"] == "paste_img": img = OnePicDeal().paste_img(img, command) continue if command["command"] == "crop_img": img = OnePicDeal().crop_img(img, command) continue if command["command"] == "radius": img = OnePicDeal().radius(img, command) continue if command["command"] == "add_text": img = OnePicDeal().add_text(img, command) continue return img image_path = r"D:\MyDocuments\PythonCode\MyPython\red_dragonfly\deal_pics\auto_capture_V2\IPC\output\-秋季订货会夏季补充给葛明明\NUM24106316\阴影图处理\NUM24106316(3)_后跟_阴影.png" to_paste_img = Image.open(image_path) data = [] bg_color = (246, 246, 246) # 单图缩放处理 view = "后跟" data.append({"command": "resize", "plugins_mode": "pixel", # pixel 相对(宽度、高度、其他参考图),或绝对像素 "base_im": {"im": ""}, # 参考基于其他图 PIL格式 "base": "width", # base:pixel,width,height,by_im 基于长边、基于短边 (基于短边时,则缩放到指定尺寸)by_im确保能塞进参考图内 "value": 1300 if view == "后跟" else 2200, # 固定值,如果为百分比,则为0 "percentage": 0, }) # 百分比 view_dict = {"俯视": (0, 0, 1100, 1200), "内里": (-1, -100, 1100, 1200), "后跟": (0, -100, 1100, 1200), "鞋底": (0, -100, 1100, 1200), } data.append({ "command": "crop_img", "img": "", "pos": {"plugins_mode": "pixel", # pixel "base": "sw", # nw,nc,ne,ec ... 各个方向参考点 "value": view_dict[view], }, "color_fill": bg_color, }) # 处理圆角 data.append({"command": "radius", # radius "plugins_mode": "relative", # pixel 相对(短边),或绝对像素 "circular_pos": (1, 0, 0, 1), # 从左上角顺时针,记录圆角数量 "value": 100, # 固定值,如果为百分比,则为0 "percentage": 0, }) # 百分比 to_paste_img = deal_one_pic(to_paste_img, data) # print(to_paste_img.size) # 粘贴到白底图上 img = Image.new("RGB", (1200, 1316), (255, 255, 255)) data = [] data.append({ "command": "paste_img", "img": {"im": to_paste_img}, "pos": {"plugins_mode": "pixel", # pixel relative "base": "wc", # nw,nc,ne,ec,... 各个方向参考点 "value": (100, 0), "percentage": "", }, "margins": (0, 0, 0, 0), # 上下左右边距 }) img = deal_one_pic(img, data) img.show()