| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- """
- 步骤:
- 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
- )
|