| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639 |
- """
- """
- 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()
|