2 Commits 2323582436 ... 2749c110e8

Author SHA1 Message Date
  zhangyh 2749c110e8 Merge branch 'dev-python' of gitlab.pubdata.cn:liangyibo/CameraMachine into dev-python 8 months ago
  zhangyh 8fa19fc793 匹配处理图片 8 months ago
5 changed files with 455 additions and 13 deletions
  1. 13 9
      python/api.py
  2. 1 1
      python/config.ini
  3. 3 2
      python/service/base_deal.py
  4. 437 0
      python/service/deal_image.py
  5. 1 1
      python/service/pic_deal.py

+ 13 - 9
python/api.py

@@ -12,9 +12,8 @@ from mcu.DeviceControl import DeviceControl
 import time
 from sqlalchemy import and_, asc, desc
 
-# from service.base_deal import  BaseDealImage
+from service.deal_image import DealImage
 from databases import DeviceConfig, SqlQuery, CRUD, select
-
 @app.get("/")
 async def index():
     # await socket_manager.send_message(msg="测试")
@@ -106,13 +105,18 @@ async def forwardRequest(request: HlmForwardRequest):
     except Exception as e:
         raise UnicornException(e)
 
-    # @app.post('/handle_detail')
-    # async def handle_detail(request: Request):
-    #
-    #     image_dir = "{}/data".format(os.getcwd())
-    #     baseDealImage = BaseDealImage(image_dir=image_dir)
-    #     result = baseDealImage.dealMoveImage(image_dir=image_dir, callback_func=None)
-    #
+
+@app.post("/handle_detail")
+async def handle_detail(request: Request):
+
+    image_dir = "{}/data".format(os.getcwd())
+    dealImage = DealImage(image_dir)
+    dealImage.header = request.headers
+    print('>>>>>>>>>>>>>>>>>请求参数')
+    print(dealImage.header)
+    result = dealImage.dealMoveImage(image_dir=image_dir, callback_func=None)
+    return result
+
 
     #
     # params = json.dump(request.query_params)

+ 1 - 1
python/config.ini

@@ -4,7 +4,7 @@ app_name=智慧拍-后端应用
 # 应用版本号
 version=1.0.0
 # 应用host地址
-host=10.56.42.176
+host=127.0.0.1
 # 应用服务启动名称
 app_run=api:app
 # 端口号

+ 3 - 2
python/service/base_deal.py

@@ -7,10 +7,10 @@ from threading import Lock
 import settings
 from collections import defaultdict
 from remove_bg_ali import RemoveBgALi, Picture
-from deal_cutout import DealCutout
+# from deal_cutout import DealCutout
 
 
-from data import DataModeAutoDealPics
+# from data import DataModeAutoDealPics
 import time
 from image_pic_deal import OnePicDeal
 
@@ -24,6 +24,7 @@ from model.photo_record import PhotoRecord
 import requests
 import copy
 
+
 """
 照片自动货号匹配 将图片放置在指定文件夹下,并自动对应不同的货号进行整理
 """

+ 437 - 0
python/service/deal_image.py

@@ -0,0 +1,437 @@
+
+import os
+
+from  natsort import natsorted,ns
+import shutil
+import exifread
+import time
+import datetime
+from databases import DeviceConfig,SqlQuery,CRUD
+import settings
+import copy
+import json
+import requests
+from service.pic_deal import Picture
+import xlsxwriter
+from PIL import Image
+
+_Type = ['.png', '.PNG', '.jpg', '.JPG', '.gif', '.GIF', ".jpge", ".JPGE"]
+
+class DealImage():
+
+
+
+
+    def __init__(self, image_dir=None):
+        self.image_dir = image_dir
+        self.header = None
+    def check_path(self, image_dir: str):
+        if not os.path.exists(image_dir):
+            os.mkdir(image_dir)
+        return True
+    def list_dir(self, path):
+        listdir = os.listdir(path)
+        return natsorted(listdir, alg=ns.PATH)
+
+    def get_date_time_original(self, file_path):
+        with open(file_path, 'rb') as file_data:
+            tags = exifread.process_file(file_data)
+            if "EXIF DateTimeOriginal" in tags:
+                return str(tags["EXIF DateTimeOriginal"])
+            else:
+                return False
+
+    def get_goods_art_no(self, date_time_original):
+        time_array = time.strptime(date_time_original, "%Y:%m:%d %H:%M:%S")
+
+        time_array = time.mktime(time_array)
+        datetime_obj = datetime.fromtimestamp(time_array)
+
+        session = SqlQuery()
+        configModel = CRUD(DeviceConfig)
+        result = configModel.read(
+            session, conditions={"photo_create_time": datetime_obj}, order_by="id", ascending=True
+        )
+        if result:
+            return result.goods_art_no, result.image_index, result.image_deal_mode
+        else:
+            return None
+
+
+
+    def get_data_from_hqt_with_goods_art_no(self, goods_art_no_list):
+        _goods_art_no_list = copy.deepcopy(goods_art_no_list)
+        _list = []
+        # 单次请求数少于20个
+        goods_art_no_dict = {}
+
+        while _goods_art_no_list:
+            goods_art_no = _goods_art_no_list.pop()
+
+            _list.append(goods_art_no)
+            if len(_list) == 20 or len(_goods_art_no_list) == 0:
+                online_goods_art_data = self.get_goods_art_no_info(
+                    goods_art_list=_list
+                )
+                if online_goods_art_data:
+                    for _goods_art_no in online_goods_art_data:
+                        goods_art_no_dict[_goods_art_no] = online_goods_art_data[
+                            _goods_art_no
+                        ]
+                _list = []
+        return goods_art_no_dict
+
+    def get_goods_art_no_info(self, numbers_list=None, goods_art_list=None):
+        # 获取商品基础信息,入参为商品的编号
+        url = "{domain}/api/backend/goods_client/goods_query".format(
+            domain=settings.APP_HOST
+        )
+        data = {
+            'goods_art_list': goods_art_list
+        }
+        data = json.dumps(data)
+        _s = requests.session().post(url=url, data=data, headers=self.header)
+        response_data = _s.json()
+
+
+        goods_number_data = {}
+        # ["", "", "", "", "", "", "", "", "", "", "", ]
+        if "data" not in response_data:
+            return {}
+
+        for data in response_data["data"]:
+            goods_number_data[data["goods_art_no"]] = {}
+            goods_number_data[data["goods_art_no"]]["商品货号"] = data["goods_art_no"].upper()
+            goods_number_data[data["goods_art_no"]]["款号"] = data["goods_number"].upper()
+            goods_number_data[data["goods_art_no"]]["商品面料"] = data["fabric"]
+            goods_number_data[data["goods_art_no"]]["商品内里"] = data["lining"]
+            goods_number_data[data["goods_art_no"]]["商品鞋底"] = data["sole"]
+            goods_number_data[data["goods_art_no"]]["鞋垫"] = data["insole"]
+            goods_number_data[data["goods_art_no"]]["颜色名称"] = data["color"]
+
+        return goods_number_data
+
+
+    def get_data_from_hqt(self, goods_number_list):
+        _goods_number_list = copy.deepcopy(goods_number_list)
+        _list = []
+        # 单次请求数少于20个
+        goods_number_dict = {}
+
+        while _goods_number_list:
+            goods_art_no = _goods_number_list.pop()
+            if "NUM" in goods_art_no:
+                goods_art_no = goods_art_no.replace("NUM", "")
+
+            _list.append(goods_art_no)
+            if len(_list) == 20 or len(_goods_number_list) == 0:
+                online_goods_art_data = self.get_goods_art_no_info(
+                    numbers_list=_list
+                )
+                if online_goods_art_data:
+                    for number in online_goods_art_data:
+                        goods_number_dict["NUM" + number] = online_goods_art_data[
+                            number
+                        ]
+                _list = []
+        return goods_number_dict
+
+    def create_folder(self, path):
+        def check_folder(__path):
+            if not os.path.exists(__path):
+                os.makedirs(__path)
+                return False
+            return True
+
+        # 文件夹不存在,创建货号子集文件夹
+        if not check_folder(path):
+            for name in ["原始图", "原始图_已抠图", "800x800", "200images"]:
+                other_path = path + "/" + name
+                check_folder(other_path)
+
+
+
+    def move_images(self, goods_art_no, goods_art_no_path, old_image_path):
+        """
+        步骤:
+        1、移动到原始图
+        Args:
+            goods_art_no:
+            goods_art_no_path:
+            old_image_path:
+
+        Returns:
+
+        """
+        # 移动到原始图
+        file = os.path.split(old_image_path)[1]
+        # 扩展名
+        e = os.path.splitext(file)[1]
+        # 获取图片序列
+        self.goods_images_count_dict[goods_art_no] += 1
+        # A9999(1).jpg
+        new_file_name = "{}({})".format(goods_art_no, self.goods_images_count_dict[goods_art_no])
+        original_image_path = "{}/原始图/{}{}".format(goods_art_no_path, new_file_name, e)
+        # 移动图片
+        shutil.move(old_image_path, original_image_path)
+
+    def dealMoveImage(self, image_dir: str, callback_func=None) -> dict:
+        if not self.check_path(image_dir=image_dir + "/历史"):
+            return {'code': 1, 'msg': '文件夹创建失败', 'data': {}}
+
+        # 遍历目标文件夹,获取有拍摄信息的图片,并按拍摄时间排序
+        files = self.list_dir(image_dir)
+        original_photo_list = []  # 原始图片列表
+        for file in files:
+            # -----图片清洗
+            file_path = image_dir + "/" + file
+            if os.path.isdir(file_path):  # 忽略文件夹
+                continue
+            file_name, suffix = os.path.splitext(file)
+            if suffix not in _Type:  # 非图片进行移除
+                shutil.move(file_path, image_dir + "/历史/" + file)
+                continue
+
+            date_time_original = self.get_date_time_original(file_path)  # 获取照片拍照时间
+            if date_time_original:
+                # 基于照片的时间,与数据库匹配goods_art_no
+                _data = self.get_goods_art_no(date_time_original)
+                if _data:
+                    # 能匹配上数据库
+                    goods_art_no, image_index, image_deal_mode = _data
+                    print("832 与数据库匹配goods_art_no", file_name, date_time_original, goods_art_no)
+                    original_photo_list.append({"file_path": file_path,
+                                                "file": file,
+                                                "date_time_original": date_time_original,
+                                                "goods_art_no": goods_art_no,
+                                                "image_index": image_index,
+                                                "real_goods_art_no": "",
+                                                "real_goods_number": "",
+                                                })
+                else:
+                    # 匹配不上报错
+                    # self.show_progress_detail("图片:{} 无法对应货号,不做处理".format(file))
+                    if callback_func:
+                        callback_func("图片:{} 无对应货号".format(file))
+                    # shutil.move(photo_dict["file_path"], self.image_dir + "/历史/" + photo_dict["file"])
+                    continue
+            else:
+                shutil.move(file_path, image_dir + "/历史/" + file)
+
+        if not original_photo_list:
+            return {"code": 1, "msg": "没有任何匹配的图片", 'data': {}}
+
+        if settings.PROJECT == "红蜻蜓":
+            # 批量请求货号图信息
+            goods_art_no_list = [x["goods_art_no"] for x in original_photo_list]
+            goods_art_no_list = list(set(goods_art_no_list))
+            goods_art_no_list = [x for x in goods_art_no_list if "NUM" not in x]
+
+            if goods_art_no_list:
+                goods_art_no_dict = self.get_data_from_hqt_with_goods_art_no(
+                    goods_art_no_list=goods_art_no_list)
+
+                for i in original_photo_list:
+                    if i["goods_art_no"] in goods_art_no_dict:
+                        i["real_goods_art_no"] = i["goods_art_no"]
+                        i["real_goods_number"] = "NUM{}".format(goods_art_no_dict[i["goods_art_no"]]["编号"])
+
+            # 批量请求编号对应信息
+            goods_number_list = [x["goods_art_no"] for x in original_photo_list]
+            goods_number_list = list(set(goods_number_list))
+            goods_number_list = [x for x in goods_number_list if "NUM" in x]
+
+            if goods_number_list:
+                goods_number_dict = self.get_data_from_hqt(goods_number_list=goods_number_list)
+                for i in original_photo_list:
+                    if i["goods_art_no"] in goods_number_dict:
+                        i["real_goods_number"] = i["goods_art_no"]
+                        i["real_goods_art_no"] = goods_number_dict[i["goods_art_no"]]["商品货号"]
+
+        # 排序需要基于拍照的文件序号进行处理
+        original_photo_list.sort(
+            key=lambda x: "{}-{}-{}".format(x["goods_art_no"], x["image_index"], x["file"]))
+
+        # print(original_photo_list)
+        # 对有拍摄信息的图片进行数据库比对,如有比对上,则移动至货号文件夹,否则移入历史文件夹
+        total_num = len(original_photo_list)
+        # 当天日期作为文件夹
+        seconds = time.time()
+        output_path = "output/{f_name}".format(f_name=time.strftime("%Y-%m-%d", time.localtime(seconds)))
+
+        # 遍历每个匹配好的数据进行处理
+        n = 0
+        for photo_dict in original_photo_list:
+            n += 1
+            # 进度条
+            goods_art_no = photo_dict["goods_art_no"]
+            original_image_path = photo_dict["file_path"]
+            # 输出货号文件夹
+            if photo_dict["real_goods_art_no"]:
+                goods_art_no = "{}@{}".format(photo_dict["real_goods_art_no"], photo_dict["real_goods_number"])
+
+            goods_art_no_path = "{output_path}/{goods_art_no}".format(output_path=output_path,
+                                                                      goods_art_no=goods_art_no)
+
+            # 创建货号下的一系列文件夹
+            self.create_folder(goods_art_no_path)
+
+            # 重命名并进行移动
+            print("开始移动:{}  {} 命名为:{}".format(goods_art_no, original_image_path, goods_art_no_path))
+            self.move_images(goods_art_no, goods_art_no_path, original_image_path)  # 货号、货号文件路径、原始图路径
+            time.sleep(0.2)
+
+
+            # self.progress_sign.emit({"type": "移动原始图片", "progress_bar_value": int(n / total_num * 100)})
+            # self.show_progress_detail("货号{} 相关文件夹创建完成,已移动原图~".format(goods_art_no))
+            if callback_func:
+                callback_func("货号{} 相关文件夹创建完成,已移动原图~".format(goods_art_no))
+
+            print("已完成移动处理")
+
+        if n != 0:
+            # if settings.MattingPics:
+            #     # 检查所有未处理的货号文件夹,查看是否有完成图片加工处理
+            #     self.deal_images()
+
+            # 自动生成一个货号表
+            print("output_path", output_path)
+            self.deal(output_path)
+
+        # 完成处理
+        # self.set_state(state_value=2)
+        return {'code': 0, 'msg': '处理完成', 'target_path': output_path, 'data': {}}
+
+
+
+    def deal(cls, dir_path):
+
+        # print("dir_path", dir_path)
+        out_excel_data = []
+        for goods_art_no_folder in os.listdir(dir_path):  # 遍历货号文件夹集合
+            if not os.path.isdir(
+                    "{}/{}".format(dir_path, goods_art_no_folder)
+            ):  # 非文件夹进行过滤
+                continue
+            if "软件" in goods_art_no_folder:
+                continue
+
+            # print("goods_art_no_folder", goods_art_no_folder)
+            # 如果存在800的主图,则优先进行使用
+            big_image_folder_path = "{}/{}/800x800".format(
+                dir_path, goods_art_no_folder
+            )
+            if not os.path.exists(big_image_folder_path):
+                os.mkdir(big_image_folder_path)
+            all_big_images = os.listdir(big_image_folder_path)
+            goods_pic_total = len(all_big_images)
+            _Type = [".png", ".PNG", ".jpg", ".JPG", ".gif", ".GIF", ".jpge", ".JPGE"]
+            thumb_image_file_path = None
+            # print("all_big_images",all_big_images)
+            if all_big_images:
+                for _file in all_big_images:
+                    # print(_file)
+                    file_name, e = os.path.splitext(_file)
+                    # print(file_name, e)
+                    if e in _Type:
+                        thumb_image_file_path = "{}/{}/800x800/{}".format(
+                            dir_path, goods_art_no_folder, _file
+                        )
+                        break
+
+            # 如果不存在主图则进行使用原始图
+            if thumb_image_file_path is None:
+                _path = "{}/{}/原始图".format(dir_path, goods_art_no_folder)
+                if not os.path.exists(_path):
+                    continue
+
+                all_original_images = os.listdir(_path)  # 遍历货号原始图文件夹
+                goods_pic_total = len(all_original_images)
+                if not all_original_images:
+                    continue
+                image_file = all_original_images[0]  # 取第一个货号图
+                image_file_path = "{}/{}/原始图/{}".format(
+                    dir_path, goods_art_no_folder, image_file
+                )
+
+                if not os.path.exists(
+                        "{}/{}/200images".format(dir_path, goods_art_no_folder)
+                ):
+                    os.mkdir("{}/{}/200images".format(dir_path, goods_art_no_folder))
+
+                thumb_image_file_path = "{}/{}/200images/{}".format(
+                    dir_path, goods_art_no_folder, image_file
+                )
+                if not os.path.exists(thumb_image_file_path):
+                    # 开始触发进行压缩生成文件
+                    shutil.copy(image_file_path, thumb_image_file_path)  # 复制文件
+                    pic = Picture(thumb_image_file_path)
+                    pic.resize(width=600)
+                    pic.save_img(thumb_image_file_path)
+            # print("thumb_image_file_path", thumb_image_file_path)
+
+            goods_number = ""
+            if "@" in goods_art_no_folder:
+                _ = goods_art_no_folder.split("@")
+                goods_art_no_folder = _[0]
+                goods_number = _[1].replace("NUM", "")
+
+            out_excel_data.append(
+                [
+                    goods_number,
+                    goods_art_no_folder,
+                    thumb_image_file_path,
+                    goods_pic_total,
+                ]
+            )
+
+        if out_excel_data:
+            out_excel_path = "{}/货号表-{}.xlsx".format(dir_path, time.time())
+            options = {
+                "default_format_properties": {
+                    "align": "left",
+                    "valign": "vcenter",
+                    "text_wrap": True,
+                }
+            }
+            book = xlsxwriter.Workbook(filename=out_excel_path, options=options)
+            sheet = book.add_worksheet("sheet1")
+            # sheet.freeze_panes(1, 2)
+            sheet.set_column("B:B", 17)
+            sheet.set_column("D:D", 20)
+
+            sheet.write_row("A1", ["编号", "原货号", "新货号", "缩略图", "原始图张数"])
+            for index, data in enumerate(out_excel_data):
+                # print(data)
+                goods_number, goods_art_no, image_file, goods_pic_total = data
+                try:
+                    im = Image.open(image_file)
+                    im_x, im_y = im.size
+                    image_width = 100
+                    image_height = int(im_y * image_width / im_x)
+                    sheet.set_row(index + 1, 95)
+                    x_scale = round(
+                        image_width / im_x, 2
+                    )  # 固定宽度/要插入的原始图片宽
+                    y_scale = round(
+                        image_height / im_y, 2
+                    )  # 固定高度/要插入的原始图片高
+                    sheet.insert_image(
+                        index + 1,
+                        3,
+                        image_file,
+                        {
+                            "x_scale": x_scale,
+                            "y_scale": y_scale,
+                            "x_offset": 5,
+                            "y_offset": 5,
+                            "object_position":1,
+                        },
+                        )
+
+
+                except:
+                    pass
+                sheet.write_row("A{}".format(index + 2), [goods_number])
+                sheet.write_row("B{}".format(index + 2), [goods_art_no])
+                sheet.write_row("E{}".format(index + 2), [goods_pic_total])

+ 1 - 1
python/service/pic_deal.py

@@ -1,7 +1,7 @@
 from PIL import Image
 from io import BytesIO
 
-from remove_bg_ali import RemoveBgALi as RemoveBg
+from service.remove_bg_ali import RemoveBgALi as RemoveBg