""" 步骤: 1、抠图 2、色阶处理,保留阴影 3、定位商品中心,并进行抠图 4、缩放定位,并粘贴到中心位置 5、粘贴水印 """ import copy import time import cv2 import numpy as np from PIL import Image, ImageEnhance import os from module.log.log import MyLogger if __name__ != '__main__': import settings class GeneratePic(object): def __init__(self): self.logger = MyLogger() pass def to_resize(self, _im, width=None, high=None): _im_x, _im_y = _im.size if width and high: if _im_x >= _im_y: high = None else: width = None if width: re_x = int(width) re_y = int(_im_y * re_x / _im_x) else: re_y = int(high) re_x = int(_im_x * re_y / _im_y) _im = _im.resize((re_x, re_y)) return _im def clean_colors(self, img): img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) return img def levels_adjust(self, img, Shadow, Midtones, Highlight, OutShadow, OutHighlight, Dim): # print(img) # dim = 3的时候调节RGB三个分量, 0调节B,1调节G,2调节R if Dim == 3: mask_shadow = img < Shadow img[mask_shadow] = Shadow mask_Highlight = img > Highlight img[mask_Highlight] = Highlight else: mask_shadow = img[..., Dim] < Shadow img[mask_shadow] = Shadow mask_Highlight = img[..., Dim] > Highlight img[mask_Highlight] = Highlight if Dim == 3: Diff = Highlight - Shadow rgbDiff = img - Shadow clRgb = np.power(rgbDiff / Diff, 1 / Midtones) outClRgb = clRgb * (OutHighlight - OutShadow) / 255 + OutShadow data = np.array(outClRgb * 255, dtype='uint8') img = data else: Diff = Highlight - Shadow rgbDiff = img[..., Dim] - Shadow clRgb = np.power(rgbDiff / Diff, 1 / Midtones) outClRgb = clRgb * (OutHighlight - OutShadow) / 255 + OutShadow data = np.array(outClRgb * 255, dtype='uint8') img[..., Dim] = data return img def calculate_average_brightness_opencv(self, img_gray, rows_to_check): # 二值化的图片 CV对象 height, width = img_gray.shape brightness_list = [] for row in rows_to_check: if 0 <= row < height: # 直接计算该行的平均亮度 row_data = img_gray[row, :] average_brightness = np.mean(row_data) brightness_list.append(average_brightness) else: print(f"警告:行号{row}超出图片范围,已跳过。") return brightness_list def run(self, image_path, cut_image_path, out_path, image_deal_mode=0, image_index=99, out_pic_size=1024, is_logo=True, out_process_path_1=None, out_process_path_2=None, resize_mode=None, **kwargs): # im 为cv对象 """ image_path:原始图 cut_image_path:抠图结果 out_path:输出文件夹 image_deal_mode:图片处理模式,1表示需要镜像处理 """ # ==========先进行剪切原图 im = Image.open(image_path) old_x, old_y = im.size cut_image = Image.open(cut_image_path) try: x1, y1, x2, y2 = cut_image.getbbox() # im_shadow.crop((x1, y1, x2, y2)).show()# 切图 except BaseException as e: print("抠图失败") return False 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)) # 切图 cut_image = cut_image.crop((new_x1, new_y1, new_x2, new_y2)) # 切图 new_x, new_y = im.size # ================自动色阶处理 _im = cv2.cvtColor(np.asarray(im), cv2.COLOR_RGB2BGR) # 背景阴影 im_shadow = cv2.cvtColor(_im, cv2.COLOR_BGR2GRAY) s = time.time() rows = [int(new_y * 19.8 / 20)] # draw = ImageDraw.Draw(im) # for row in rows: # draw.line((0, row, new_x, row), fill=128, width=3) # im.show() _im_shadow = copy.copy(im_shadow) Midtones = 0.52 Highlight = 235 k = 20 while k: k -= 1 Midtones += 0.1 Highlight -= 5 _im_shadow = self.levels_adjust(img=im_shadow, Shadow=0, Midtones=Midtones, Highlight=Highlight, OutShadow=0, OutHighlight=255, Dim=3) brightness_list = self.calculate_average_brightness_opencv(img_gray=_im_shadow, rows_to_check=rows) print(brightness_list) if brightness_list[0] >= 254: break print(time.time() - s) im_shadow = Image.fromarray(cv2.cvtColor(_im_shadow, cv2.COLOR_BGR2RGB)) im_shadow.paste(cut_image, (0, 0), cut_image) # 把原图粘贴回去,避免色差 # 保存带有阴影的底图,没有logo if out_process_path_1: out_image_1 = im_shadow.copy() if image_deal_mode == 1: out_image_1 = out_image_1.transpose(Image.FLIP_LEFT_RIGHT) out_image_1.save(out_process_path_1) # 保存抠图结果,没有底图,没有logo if out_process_path_2: out_image_2 = cut_image.copy() if image_deal_mode == 1: out_image_2 = out_image_2.transpose(Image.FLIP_LEFT_RIGHT) out_image_2.save(out_process_path_2) # im_shadow.show() # 主图物体的缩放依据大小 if resize_mode is None: im_shadow = self.to_resize(_im=im_shadow, width=1400, high=1400) cut_image = self.to_resize(_im=cut_image, width=1400, high=1400) elif resize_mode == 1: im_shadow = self.to_resize(_im=im_shadow, width=1400, high=1400) cut_image = self.to_resize(_im=cut_image, width=1400, high=1400) elif resize_mode == 2: if im_shadow.height <= im_shadow.width * 1.2: im_shadow = self.to_resize(_im=im_shadow, width=650) cut_image = self.to_resize(_im=cut_image, width=650) else: im_shadow = self.to_resize(_im=im_shadow, high=1400) cut_image = self.to_resize(_im=cut_image, high=1400) if image_deal_mode == 1: # 翻转 im_shadow = im_shadow.transpose(Image.FLIP_LEFT_RIGHT) cut_image = cut_image.transpose(Image.FLIP_LEFT_RIGHT) # 创建底层背景 image_bg = Image.new("RGB", (1600, 1600), (255, 255, 255)) image_bg_x, image_bg_y = image_bg.size image_x, image_y = im_shadow.size _x = int((image_bg_x - image_x) / 2) _y = int((image_bg_y - image_y) / 2) image_bg.paste(im_shadow, (_x, _y)) image_bg.paste(cut_image, (_x, _y), cut_image) # 再叠加原图避免色差 if is_logo: logo_path = "" if settings.PROJECT == "红蜻蜓": logo_path = r"resources\LOGO\HQT\logo.png" elif settings.PROJECT == "惠利玛": if "小苏" in settings.Company: logo_path = r"resources\LOGO\xiaosushuoxie\logo.png" elif "惠利玛" in settings.Company: logo_path = r"resources\LOGO\HLM\logo.png" else: pass if not logo_path: logo_im = Image.new("RGBA", (1600, 1600), (0, 0, 0, 0)) else: if os.path.exists(logo_path): logo_im = Image.open(logo_path) else: logo_im = Image.new("RGBA", (1600, 1600), (0, 0, 0, 0)) image_bg.paste(logo_im, (0, 0), logo_im) image_bg = image_bg.resize((out_pic_size, out_pic_size), Image.BICUBIC) # image_bg.show() image_bg.save(out_path, quality=100, dpi=(300, 300), format="JPEG") return True class GeneratePicPiJu(object): def __init__(self): pass def calculate_average_brightness_opencv(self, img_gray, rows_to_check): # 二值化的图片 CV对象 height, width = img_gray.shape brightness_list = [] for row in rows_to_check: if 0 <= row < height: # 直接计算该行的平均亮度 row_data = img_gray[row, :] average_brightness = np.mean(row_data) brightness_list.append(average_brightness) else: print(f"警告:行号{row}超出图片范围,已跳过。") return brightness_list def to_resize(self, _im, width=None, high=None): _im_x, _im_y = _im.size if width and high: if _im_x >= _im_y: high = None else: width = None if width: re_x = int(width) re_y = int(_im_y * re_x / _im_x) else: re_y = int(high) re_x = int(_im_x * re_y / _im_y) _im = _im.resize((re_x, re_y)) return _im def run(self, image_path, cut_image_path, out_path, image_deal_mode=0, image_index=99, out_pic_size=800, is_logo=True, out_process_path_1=None, out_process_path_2=None, max_box=None): # im 为cv对象 """ image_path:原始图 cut_image_path:抠图结果 out_path:输出文件夹 image_deal_mode:图片处理模式,1表示需要镜像处理 """ # ==========先进行剪切原图 im = Image.open(image_path) old_x, old_y = im.size cut_image = Image.open(cut_image_path) try: x1, y1, x2, y2 = cut_image.getbbox() # im_shadow.crop((x1, y1, x2, y2)).show()# 切图 except BaseException as e: print("抠图失败") return False 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)) # 切图 cut_image = cut_image.crop((new_x1, new_y1, new_x2, new_y2)) # 切图 new_x, new_y = im.size # ================自动色阶处理 _im = cv2.cvtColor(np.asarray(im), cv2.COLOR_RGB2BGR) # 背景阴影 im_shadow = cv2.cvtColor(_im, cv2.COLOR_BGR2GRAY) s = time.time() rows = [int(new_y * 19.8 / 20)] # draw = ImageDraw.Draw(im) # for row in rows: # draw.line((0, row, new_x, row), fill=128, width=3) # im.show() _im_shadow = copy.copy(im_shadow) Midtones = 0.52 Highlight = 235 k = 20 while k: k -= 1 Midtones += 0.1 Highlight -= 5 _im_shadow = self.levels_adjust(img=im_shadow, Shadow=0, Midtones=Midtones, Highlight=Highlight, OutShadow=0, OutHighlight=255, Dim=3) brightness_list = self.calculate_average_brightness_opencv(img_gray=_im_shadow, rows_to_check=rows) print(brightness_list) if brightness_list[0] >= 254: break print(time.time() - s) im_shadow = Image.fromarray(cv2.cvtColor(_im_shadow, cv2.COLOR_BGR2RGB)) im_shadow.paste(cut_image, (0, 0), cut_image) # 把原图粘贴回去,避免色差 # 保存带有阴影的底图,没有logo if out_process_path_1: out_image_1 = im_shadow.copy() if image_deal_mode == 1: out_image_1 = out_image_1.transpose(Image.FLIP_LEFT_RIGHT) out_image_1.save(out_process_path_1) # 保存抠图结果,没有底图,没有logo if out_process_path_2: out_image_2 = cut_image.copy() if image_deal_mode == 1: out_image_2 = out_image_2.transpose(Image.FLIP_LEFT_RIGHT) out_image_2.save(out_process_path_2) # im_shadow.show() if max_box: im_shadow = self.to_resize(_im=im_shadow, width=max_box[0], high=max_box[1]) cut_image = self.to_resize(_im=cut_image, width=max_box[0], high=max_box[1]) else: if image_index != 3: im_shadow = self.to_resize(_im=im_shadow, width=1000, high=1000) cut_image = self.to_resize(_im=cut_image, width=1000, high=1000) else: im_shadow = self.to_resize(_im=im_shadow, width=650) cut_image = self.to_resize(_im=cut_image, width=650) if image_deal_mode == 1: # 翻转 im_shadow = im_shadow.transpose(Image.FLIP_LEFT_RIGHT) cut_image = cut_image.transpose(Image.FLIP_LEFT_RIGHT) # 创建底层背景 image_bg = Image.new("RGB", (1600, 1600), (255, 255, 255)) image_bg_x, image_bg_y = image_bg.size image_x, image_y = im_shadow.size _x = int((image_bg_x - image_x) / 2) _y = int((image_bg_y - image_y) / 2) image_bg.paste(im_shadow, (_x, _y)) image_bg.paste(cut_image, (_x, _y), cut_image) if is_logo: logo_path = "" if settings.PROJECT == "红蜻蜓": logo_path = r"resources\LOGO\HQT\logo.png" elif settings.PROJECT == "惠利玛": if "小苏" in settings.Company: logo_path = r"resources\LOGO\xiaosushuoxie\logo.png" elif "惠利玛" in settings.Company: logo_path = r"resources\LOGO\HLM\logo.png" else: pass if not logo_path: logo_im = Image.new("RGBA", (1600, 1600), (0, 0, 0, 0)) else: if os.path.exists(logo_path): logo_im = Image.open(logo_path) else: logo_im = Image.new("RGBA", (1600, 1600), (0, 0, 0, 0)) image_bg.paste(logo_im, (0, 0), logo_im) image_bg = image_bg.resize((out_pic_size, out_pic_size), Image.BICUBIC) # image_bg.show() image_bg.save(out_path, quality=100, dpi=(300, 300), format="JPEG") return True def increase_brightness(self, im, brightness_factor): # 打开图片 # 将图片转换为RGB模式 # image = image.convert("RGBA") # 获取图片的亮度值 enhancer = ImageEnhance.Brightness(im) brightness = enhancer.enhance(brightness_factor) return brightness def clean_colors(self, img): img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) return img def levels_adjust(self, img, Shadow, Midtones, Highlight, OutShadow, OutHighlight, Dim): # print(img) # dim = 3的时候调节RGB三个分量, 0调节B,1调节G,2调节R if Dim == 3: mask_shadow = img < Shadow img[mask_shadow] = Shadow mask_Highlight = img > Highlight img[mask_Highlight] = Highlight else: mask_shadow = img[..., Dim] < Shadow img[mask_shadow] = Shadow mask_Highlight = img[..., Dim] > Highlight img[mask_Highlight] = Highlight if Dim == 3: Diff = Highlight - Shadow rgbDiff = img - Shadow clRgb = np.power(rgbDiff / Diff, 1 / Midtones) outClRgb = clRgb * (OutHighlight - OutShadow) / 255 + OutShadow data = np.array(outClRgb * 255, dtype='uint8') img = data else: Diff = Highlight - Shadow rgbDiff = img[..., Dim] - Shadow clRgb = np.power(rgbDiff / Diff, 1 / Midtones) outClRgb = clRgb * (OutHighlight - OutShadow) / 255 + OutShadow data = np.array(outClRgb * 255, dtype='uint8') img[..., Dim] = data return img if __name__ == '__main__': # 测试皮具主图生成 for jpg_name in os.listdir("image"): if "png" in jpg_name: continue file_name = os.path.splitext(jpg_name)[0] original_image_path = r"image\{}.jpg".format(file_name) original_move_bg_image_path = r"image\{}.png".format(file_name) out_path = r"out\{}.jpg".format(file_name) is_image_deal_mode = 1 resize_mode = 1 print(original_image_path) GeneratePicPiJu().run(image_path=original_image_path, cut_image_path=original_move_bg_image_path, out_path=out_path, image_deal_mode=is_image_deal_mode, # resize_mode=resize_mode, out_pic_size=1600, is_logo=False, max_box=None )