module_matching_photos.py 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. # from UI.matching_photos.matching_photos import Ui_Form as matching_photos_Ui_Form
  2. import os
  3. from UI.matching_photos.matching_and_cutout_photos import (
  4. Ui_Form as matching_photos_Ui_Form,
  5. )
  6. from import_qt_mode import *
  7. import settings
  8. from collections import defaultdict
  9. from module.service.base_deal_image import BaseDealImage
  10. from module.view_control.generate_goods_art_no_table.module_generate_goods_art_no_table import GenerateGoodsArtNoTable
  11. from module.view_control.matching_photos.data import DataModeMatchPhoto
  12. from module.view_control.manual_image_matching.m_image_matching_cotrol import MainMatchingWindow
  13. from PySide6.QtGui import QPixmap
  14. from PIL import Image
  15. import io
  16. import threading
  17. import shutil
  18. import time
  19. from module.base_mode.pic_deal import PicDeal
  20. # import exifread
  21. from module.base_mode.base import *
  22. from module.view_control.MineQWidget import MineQWidget, DialogShow
  23. from threading import Event
  24. from functools import partial
  25. from UI.matching_photos.temp_item import Ui_Form as UI_temp_item
  26. """
  27. 照片自动货号匹配 将图片放置在指定文件夹下,并自动对应不同的货号进行整理
  28. """
  29. class MatchingPhotos(MineQWidget):
  30. progress_sign = Signal(dict)
  31. info_sign = Signal(str)
  32. text_show = Signal(str)
  33. def __init__(self):
  34. super().__init__()
  35. self.image_dir = settings.PhotoImageDir
  36. self.ui = matching_photos_Ui_Form()
  37. self.ui.setupUi(self)
  38. # 0禁用 1进行中 2已结束
  39. self.state = 2
  40. self.event = Event()
  41. self.goods_images_count_dict = defaultdict(int)
  42. self.data_match_photo = DataModeMatchPhoto()
  43. self.excel_path = ""
  44. # 上次使用的详情模板
  45. self.last_temp = settings.MATCHING_LAST_TEMP
  46. # 指定单独处理的颜色文件夹
  47. self.special_goods_art_no_folder = []
  48. self.init()
  49. self.show()
  50. def init(self):
  51. # 文本
  52. self.ui.textBrowser.clear()
  53. text = """请将capture One 加工后的图片放在指定目录下(目录为当前文件夹下的{}/data文件夹),务必确保导出的图片有拍摄时间信息。""".format(os.getcwd())
  54. self.ui.textBrowser.append(text)
  55. self.ui.tabWidget.setCurrentIndex(0)
  56. # 页面视图1
  57. self.ui.stackedWidget.setCurrentIndex(0)
  58. self.text_show.connect(self.append_text_to_browser)
  59. self.show_img_dir()
  60. self.ui.select_path.mousePressEvent = self.change_img_dir
  61. self.ui.progressBar.setValue(0)
  62. self.ui.progressBar.setMaximum(100)
  63. self.ui.progressBar.setValue(0)
  64. self.ui.progressBar.hide()
  65. self.ui.line_image_pos.setText(settings.cutimage_dict['imageorder'])
  66. self.ui.need_resize.setText(settings.cutimage_dict['resize_image_view'])
  67. self.ui.check_image_total.setChecked(bool(settings.cutimage_dict['is_check_number']))
  68. self.ui.check_is_pass.setChecked(bool(settings.cutimage_dict['is_filter']))
  69. print(settings.cutimage_dict)
  70. if settings.DEFAULT_CUTOUT_MODE == '普通抠图':
  71. self.ui.cutout_nomal.setChecked(True)
  72. elif settings.DEFAULT_CUTOUT_MODE == ' 精细化抠图':
  73. self.ui.cutout_exquisite.setChecked(True)
  74. if not bool(settings.IsExquisiteMode):
  75. self.ui.cutout_exquisite.setEnabled(False)
  76. # 展示是否指定内容抠图
  77. self.ui.is_do_other.toggled.connect(self.change_do_special_treatment)
  78. self.change_do_special_treatment()
  79. self.progress_sign.connect(self.show_progress)
  80. self.ui.run.clicked.connect(self.run_image_cut) # 抠图与主图加工
  81. self.ui.run_2.clicked.connect(self.run_matching) # 匹配图片
  82. self.ui.back.clicked.connect(self.back)
  83. # 页面视图2
  84. self.ui.back.hide()
  85. self.set_logo_selected()
  86. # 手动匹配图片
  87. self.ui.manual_matching_pic.mousePressEvent = self.manual_matching_pic_mousePressEvent
  88. # 切换是否特殊处理的开关
  89. def change_do_special_treatment(self, *args):
  90. if self.ui.is_do_other.isChecked():
  91. self.ui.show_deal_condition.show()
  92. else:
  93. self.ui.show_deal_condition.hide()
  94. # 设置选择logo模板
  95. def set_logo_selected(self):
  96. logo_root_path = ""
  97. if settings.PROJECT == "红蜻蜓":
  98. logo_root_path = r"{}\resources\LOGO\HQT".format(os.getcwd())
  99. elif settings.PROJECT == "惠利玛":
  100. if "小苏" in settings.Company:
  101. logo_root_path = r"{}\resources\LOGO\xiaosushuoxie".format(os.getcwd())
  102. if "惠利玛" in settings.Company:
  103. logo_root_path = r"{}\resources\LOGO\HLM".format(os.getcwd())
  104. self.logo_path_dict = {"请选择": "", "无logo": ""}
  105. if logo_root_path:
  106. if os.path.exists(logo_root_path):
  107. image_list = get_images(logo_root_path)
  108. print("111111111 image_list", image_list)
  109. for image_data in image_list:
  110. self.logo_path_dict[image_data["file_name"]] = image_data["file_path"]
  111. self.ui.logo_select_ui.addItems([x for x in self.logo_path_dict])
  112. self.ui.logo_select_ui.setCurrentText("请选择")
  113. if settings.MATCHING_LAST_LOGO_TEMP:
  114. if settings.MATCHING_LAST_LOGO_TEMP in [x for x in self.logo_path_dict]:
  115. self.ui.logo_select_ui.setCurrentText(settings.MATCHING_LAST_LOGO_TEMP)
  116. def manual_matching_pic_mousePressEvent(self, event):
  117. if not self.image_dir:
  118. a = QMessageBox.question(
  119. self,
  120. "确认",
  121. "请先选择目标文件夹",
  122. QMessageBox.Yes,
  123. )
  124. return
  125. self.manual = MainMatchingWindow(root_path=self.image_dir)
  126. @Slot()
  127. def on_stop_clicked(self):
  128. self.event.set()
  129. pass
  130. def change_img_dir(self, *args):
  131. folder = QFileDialog.getExistingDirectory(self, "选取文件夹", "./")
  132. print(folder)
  133. settings.set_config(data_dict={"photo_image_dir": folder})
  134. # 清空已特殊选择等处理
  135. self.ui.is_do_other.setChecked(False)
  136. self.show_img_dir(image_dir=folder)
  137. def show_img_dir(self, image_dir=None):
  138. if image_dir:
  139. self.image_dir = image_dir
  140. else:
  141. self.image_dir = settings.PhotoImageDir
  142. if self.image_dir:
  143. self.ui.path_name.show()
  144. self.ui.path_name.setText(self.image_dir)
  145. else:
  146. self.ui.path_name.hide()
  147. def show_progress(self, data):
  148. progress_bar_value = data["progress_bar_value"]
  149. self.ui.progressBar.setValue(progress_bar_value)
  150. def check(self):
  151. _path = self.image_dir + "/历史"
  152. if not os.path.exists(_path):
  153. os.mkdir(_path)
  154. return True
  155. def set_state(self, state_value: int):
  156. # 0禁用 1进行中 2已结束
  157. if state_value not in [0, 1, 2]:
  158. return
  159. self.state = state_value
  160. if self.state == 0:
  161. self.ui.stackedWidget.setCurrentIndex(0)
  162. if self.state == 1:
  163. self.ui.stackedWidget.setCurrentIndex(1)
  164. self.ui.back.hide()
  165. self.ui.stop.show()
  166. self.ui.textBrowser_4.clear()
  167. self.ui.textBrowser_4.show()
  168. self.event.clear()
  169. if self.state == 2:
  170. self.ui.stackedWidget.setCurrentIndex(1)
  171. self.ui.back.show()
  172. self.ui.stop.hide()
  173. def back(self):
  174. self.ui.stackedWidget.setCurrentIndex(0)
  175. self.ui.back.hide()
  176. self.ui.run.show()
  177. self.ui.stop.hide()
  178. self.ui.textBrowser_4.clear()
  179. self.ui.textBrowser_4.hide()
  180. def check_first_call_back(self, data):
  181. # 首次数据校验的信息返回
  182. # self.show_message(text="22222222222222222222222")
  183. # QMessageBox.critical(self, "警告", "1111111", QMessageBox.Ok)
  184. code = data["code"]
  185. if data["message"]:
  186. button_1, button_2, button_3 = None, None, None
  187. button_1 = "移除"
  188. button_2 = "继续"
  189. text = data["message"]
  190. my_dialog = DialogShow(self, text=text, button_1=button_1, button_2=button_2)
  191. ret = my_dialog.exec()
  192. print(my_dialog.flag_name)
  193. if "移除" in my_dialog.flag_name:
  194. pass
  195. if "继续" in my_dialog.flag_name:
  196. pass
  197. def check_test(self, test):
  198. print(test)
  199. time.sleep(3)
  200. return_data = {"code": 99,
  201. "message": "messagemessagemessagemessagemessagemessagemessage",
  202. "data": {"error_folder_list": [],
  203. "goods_no_dict": {},
  204. "succeed_folder_list": [],
  205. }}
  206. return return_data
  207. def run_matching11111(self, *args):
  208. func = partial(self.check_test, test=1111111)
  209. self.do_thread_run(func=func, call_back=self.check_first_call_back, time_out=30)
  210. def run_matching(self, *args):
  211. if settings.PROJECT == "红蜻蜓":
  212. if not settings.IsLogin:
  213. a = QMessageBox.question(
  214. self,
  215. "确认",
  216. "请先进行登录红蜻蜓账号",
  217. QMessageBox.Yes | QMessageBox.No,
  218. )
  219. return
  220. self.set_state(state_value=1)
  221. self.goods_images_count_dict = {}
  222. self.goods_images_count_dict = defaultdict(int)
  223. self.do_thread_run(func=self.run_by_thread, call_back=self.matchingCallBack, time_out=60)
  224. # self.t = threading.Thread(target=self.run_by_thread, args=())
  225. # self.t.start()
  226. def matchingCallBack(self, data: dict):
  227. self.set_state(2)
  228. if data['code'] == 0:
  229. self.show_progress_detail('处理完成')
  230. button_1, button_2, button_3 = None, None, None
  231. button_1 = "去抠图"
  232. text = '移动完成'
  233. my_dialog = DialogShow(self, text=text, button_1=button_1, button_2=button_2)
  234. ret = my_dialog.exec()
  235. if "去抠图" in my_dialog.flag_name:
  236. self.back()
  237. self.ui.tabWidget.setCurrentIndex(1)
  238. path = os.getcwd() + "/" + data['target_path']
  239. self.ui.path_name.setText(path)
  240. else:
  241. self.show_progress_detail(data['msg'])
  242. text = data['msg']
  243. my_dialog = DialogShow(self, text=text)
  244. ret = my_dialog.exec()
  245. def run_image_cut(self, *args):
  246. if not settings.IsLogin:
  247. QMessageBox.question(
  248. self, "确认", "请先登录", QMessageBox.Yes | QMessageBox.No
  249. )
  250. return
  251. logo_name = self.ui.logo_select_ui.currentText()
  252. if logo_name == "请选择":
  253. QMessageBox.question(
  254. self, "确认", "请先选择logo模板", QMessageBox.Yes | QMessageBox.No
  255. )
  256. return
  257. if self.ui.cutout_exquisite.isChecked() and not bool(settings.IsExquisiteMode):
  258. QMessageBox.question(
  259. self, "确认", "暂无 精细化抠图权限", QMessageBox.Yes | QMessageBox.No
  260. )
  261. return
  262. self.set_state(state_value=1)
  263. self.t = threading.Thread(target=self.threadImageCut, args=())
  264. self.t.start()
  265. def threadImageCut(
  266. self,
  267. ):
  268. image_dir = self.ui.path_name.text()
  269. baseDealImage = BaseDealImage(image_dir=image_dir)
  270. image_order = self.ui.line_image_pos.text()
  271. is_check_number = self.ui.check_image_total.isChecked()
  272. is_filter = self.ui.check_is_pass.isChecked()
  273. resize_image_view = self.ui.need_resize.text()
  274. logo_name = self.ui.logo_select_ui.currentText()
  275. settings.MATCHING_LAST_LOGO_TEMP = logo_name
  276. logo_path = self.logo_path_dict[logo_name]
  277. cutout_mode = '1'
  278. if self.ui.cutout_exquisite.isChecked():
  279. cutout_mode = '2'
  280. configData = {
  281. 'imageorder': image_order,
  282. 'resize_image_view': resize_image_view,
  283. 'is_check_number': str(is_check_number),
  284. 'is_filter': str(is_filter),
  285. 'cutout_mode': str(cutout_mode),
  286. 'matching_mode_last': settings.MATCHING_MODE_LAST,
  287. "matching_last_temp": self.last_temp,
  288. "matching_last_logo_temp": logo_name,
  289. }
  290. settings.cutimage_dict['imageorder'] = image_order
  291. settings.cutimage_dict['resize_image_view'] = resize_image_view
  292. settings.cutimage_dict['is_check_number'] = str(is_check_number)
  293. settings.cutimage_dict['is_filter'] = str(is_filter)
  294. settings.cutimage_dict['cutout_mode'] = str(cutout_mode)
  295. settings.set_config(data_dict=configData, section='cutimage')
  296. # =================整理要处理的货号文件夹数据=================
  297. is_ok = True
  298. all_goods_art_no_folder_data = get_all_goods_art_no_folder(path=image_dir)
  299. todo_goods_art_no_folder_name_list = []
  300. if not self.ui.is_do_other.isChecked():
  301. todo_goods_art_no_folder_name_list = [x["folder_name"] for x in all_goods_art_no_folder_data]
  302. else:
  303. is_filter = False
  304. specified_goods_art_no_folder = self.ui.special_goods_art_no_folder_line.text()
  305. specified_goods_art_no_folder = specified_goods_art_no_folder.strip()
  306. specified_goods_art_no_folder = specified_goods_art_no_folder.replace(",", ",")
  307. if not specified_goods_art_no_folder:
  308. self.show_progress_detail('请手动输入文件夹名称(多选),或关闭指定文件夹模式')
  309. is_ok = False
  310. else:
  311. specified_goods_art_no_folder_list = specified_goods_art_no_folder.split(",")
  312. all_folder_name_list = [x["folder_name"] for x in all_goods_art_no_folder_data]
  313. for goods_art_no_folder_name in specified_goods_art_no_folder_list:
  314. if goods_art_no_folder_name:
  315. if goods_art_no_folder_name not in all_folder_name_list:
  316. self.show_progress_detail('文件夹:{},在您选的目录下不存在'.format(goods_art_no_folder_name))
  317. is_ok = False
  318. else:
  319. todo_goods_art_no_folder_name_list.append(goods_art_no_folder_name)
  320. if not is_ok:
  321. self.set_state(state_value=2)
  322. return
  323. # 清空指定文件夹的已抠图文件
  324. print("todo_goods_art_no_folder_name_list",todo_goods_art_no_folder_name_list)
  325. if self.ui.is_do_other.isChecked():
  326. if self.ui.is_clean_cutout_image.isChecked():
  327. for goods_art_no_folder_name in todo_goods_art_no_folder_name_list:
  328. goods_art_no_folder_path = "{}/{}/原始图_已抠图".format(image_dir, goods_art_no_folder_name)
  329. print("goods_art_no_folder_path",goods_art_no_folder_path)
  330. if os.path.exists(goods_art_no_folder_path):
  331. remove_all_file(goods_art_no_folder_path)
  332. if settings.IS_TEST:
  333. result = baseDealImage.cutoutImage(
  334. image_dir=image_dir,
  335. todo_goods_art_no_folder_name_list=todo_goods_art_no_folder_name_list,
  336. image_order=image_order,
  337. is_check_number=is_check_number,
  338. is_filter=is_filter,
  339. resize_image_view=resize_image_view,
  340. callback_func=self.show_progress_detail,
  341. event=self.event,
  342. cutout_mode=cutout_mode,
  343. logo_path=logo_path,
  344. )
  345. if "code" in result and result['code'] != 0:
  346. self.show_progress_detail(result['msg'])
  347. else:
  348. self.show_progress_detail('处理完成')
  349. else:
  350. try:
  351. result = baseDealImage.cutoutImage(
  352. image_dir=image_dir,
  353. image_order=image_order,
  354. todo_goods_art_no_folder_name_list=todo_goods_art_no_folder_name_list,
  355. is_check_number=is_check_number,
  356. is_filter=is_filter,
  357. resize_image_view=resize_image_view,
  358. callback_func=self.show_progress_detail,
  359. event=self.event,
  360. cutout_mode=cutout_mode,
  361. logo_path=logo_path,
  362. )
  363. if "code" in result and result['code'] != 0:
  364. self.show_progress_detail(result['msg'])
  365. else:
  366. self.show_progress_detail('处理完成')
  367. except BaseException as e:
  368. print(e)
  369. self.show_progress_detail('程序异常')
  370. self.set_state(state_value=2)
  371. def show_progress_detail(self, text):
  372. self.text_show.emit(text)
  373. def append_text_to_browser(self, text):
  374. self.ui.textBrowser_4.append(text)
  375. def run_by_thread(self):
  376. image_dir = "{}/data".format(os.getcwd())
  377. baseDealImage = BaseDealImage(image_dir=image_dir)
  378. # result = baseDealImage.dealMoveImage(
  379. # image_dir=settings.PhotoOutputDir, callback_func=self.show_progress_detail
  380. # )
  381. result = baseDealImage.dealMoveImage(
  382. image_dir=image_dir, callback_func=self.show_progress_detail
  383. )
  384. return result
  385. def run_by_thread_backup(self):
  386. if not self.check():
  387. return
  388. # 遍历目标文件夹,获取有拍摄信息的图片,并按拍摄时间排序
  389. files = os.listdir(self.image_dir)
  390. _Type = [".png", ".PNG", ".jpg", ".JPG", ".gif", ".GIF", ".jpge", ".JPGE"]
  391. original_photo_list = [] # 原始图片列表
  392. for file in files:
  393. # -----图片清洗
  394. file_path = self.image_dir + "/" + file
  395. if os.path.isdir(file_path): # 忽略文件夹
  396. continue
  397. file_name, e = os.path.splitext(file)
  398. if e not in _Type: # 非图片进行移除
  399. shutil.move(file_path, self.image_dir + "/历史/" + file)
  400. continue
  401. date_time_original = self.get_date_time_original(
  402. file_path
  403. ) # 获取照片拍照时间
  404. if date_time_original:
  405. # 基于照片的时间,与数据库匹配goods_art_no
  406. _data = self.data_match_photo.get_goods_art_no(date_time_original)
  407. if _data:
  408. # 能匹配上数据库
  409. goods_art_no, image_index, image_deal_mode = _data
  410. print(
  411. "与数据库匹配goods_art_no",
  412. file_name,
  413. date_time_original,
  414. goods_art_no,
  415. )
  416. original_photo_list.append(
  417. {
  418. "file_path": file_path,
  419. "file": file,
  420. "date_time_original": date_time_original,
  421. "goods_art_no": goods_art_no,
  422. "image_index": image_index,
  423. "real_goods_art_no": "",
  424. "real_goods_number": "",
  425. }
  426. )
  427. else:
  428. # 匹配不上报错
  429. self.show_progress_detail(
  430. "图片:{} 无法对应货号,不做处理".format(file)
  431. )
  432. # shutil.move(photo_dict["file_path"], self.image_dir + "/历史/" + photo_dict["file"])
  433. continue
  434. else:
  435. shutil.move(file_path, self.image_dir + "/历史/" + file)
  436. if not original_photo_list:
  437. self.show_progress_detail("没有任何匹配的图片~")
  438. self.set_state(state_value=2)
  439. return
  440. if settings.PROJECT == "红蜻蜓":
  441. # 批量请求货号图信息
  442. goods_art_no_list = [x["goods_art_no"] for x in original_photo_list]
  443. goods_art_no_list = list(set(goods_art_no_list))
  444. goods_art_no_list = [x for x in goods_art_no_list if "NUM" not in x]
  445. if goods_art_no_list:
  446. goods_art_no_dict = (
  447. self.data_match_photo.get_data_from_hqt_with_goods_art_no(
  448. goods_art_no_list=goods_art_no_list
  449. )
  450. )
  451. for i in original_photo_list:
  452. if i["goods_art_no"] in goods_art_no_dict:
  453. i["real_goods_art_no"] = i["goods_art_no"]
  454. i["real_goods_number"] = "NUM{}".format(
  455. goods_art_no_dict[i["goods_art_no"]]["编号"]
  456. )
  457. # 批量请求编号对应信息
  458. goods_number_list = [x["goods_art_no"] for x in original_photo_list]
  459. goods_number_list = list(set(goods_number_list))
  460. goods_number_list = [x for x in goods_number_list if "NUM" in x]
  461. if goods_number_list:
  462. goods_number_dict = self.data_match_photo.get_data_from_hqt(
  463. goods_number_list=goods_number_list
  464. )
  465. for i in original_photo_list:
  466. if i["goods_art_no"] in goods_number_dict:
  467. i["real_goods_number"] = i["goods_art_no"]
  468. i["real_goods_art_no"] = goods_number_dict[i["goods_art_no"]][
  469. "商品货号"
  470. ]
  471. # 排序需要基于拍照的文件序号进行处理
  472. original_photo_list.sort(
  473. key=lambda x: "{}-{}-{}".format(
  474. x["goods_art_no"], x["image_index"], x["file"]
  475. )
  476. )
  477. print(original_photo_list)
  478. # 对有拍摄信息的图片进行数据库比对,如有比对上,则移动至货号文件夹,否则移入历史文件夹
  479. total_num = len(original_photo_list)
  480. # 当天日期作为文件夹
  481. seconds = time.time()
  482. output_path = "output/{f_name}".format(
  483. f_name=time.strftime("%Y-%m-%d", time.localtime(seconds))
  484. )
  485. # 遍历每个匹配好的数据进行处理
  486. n = 0
  487. for photo_dict in original_photo_list:
  488. n += 1
  489. # 进度条
  490. goods_art_no = photo_dict["goods_art_no"]
  491. original_image_path = photo_dict["file_path"]
  492. # 输出货号文件夹
  493. if photo_dict["real_goods_art_no"]:
  494. goods_art_no = "{}@{}".format(
  495. photo_dict["real_goods_art_no"], photo_dict["real_goods_number"]
  496. )
  497. goods_art_no_path = "{output_path}/{goods_art_no}".format(
  498. output_path=output_path, goods_art_no=goods_art_no
  499. )
  500. # 创建货号下的一系列文件夹
  501. self.create_folder(goods_art_no_path)
  502. # 重命名并进行移动
  503. self.move_images(
  504. goods_art_no, goods_art_no_path, original_image_path
  505. ) # 货号、货号文件路径、原始图路径
  506. self.progress_sign.emit(
  507. {"type": "移动原始图片", "progress_bar_value": int(n / total_num * 100)}
  508. )
  509. self.show_progress_detail(
  510. "货号{} 相关文件夹创建完成,已移动原图~".format(goods_art_no)
  511. )
  512. if n != 0:
  513. # if settings.MattingPics:
  514. # # 检查所有未处理的货号文件夹,查看是否有完成图片加工处理
  515. # self.deal_images()
  516. # 自动生成一个货号表
  517. print("output_path", output_path)
  518. GenerateGoodsArtNoTable.deal(output_path)
  519. # 完成处理
  520. self.set_state(state_value=2)
  521. def move_images(self, goods_art_no, goods_art_no_path, old_image_path):
  522. """
  523. 步骤:
  524. 1、移动到原始图
  525. Args:
  526. goods_art_no:
  527. goods_art_no_path:
  528. old_image_path:
  529. Returns:
  530. """
  531. # 移动到原始图
  532. file = os.path.split(old_image_path)[1]
  533. # 扩展名
  534. e = os.path.splitext(file)[1]
  535. # 获取图片序列
  536. self.goods_images_count_dict[goods_art_no] += 1
  537. # A9999(1).jpg
  538. new_file_name = "{}({})".format(
  539. goods_art_no, self.goods_images_count_dict[goods_art_no]
  540. )
  541. original_image_path = "{}/原始图/{}{}".format(
  542. goods_art_no_path, new_file_name, e
  543. )
  544. # 移动图片
  545. shutil.move(old_image_path, original_image_path)
  546. def deal_images(self):
  547. """
  548. 2、压缩并上传平台获取抠图
  549. 3、抠图处理成白底图
  550. 4、做成800*800/200*200
  551. :return:
  552. """
  553. output_path = "output"
  554. """
  555. 扫描文档,检查有哪些需要进行抠图等处理
  556. """
  557. to_do_images_total = 0
  558. for _date_folder in os.listdir(output_path):
  559. if not os.path.isdir("{}/{}".format(output_path, _date_folder)):
  560. continue
  561. for goods_art_no_folder in os.listdir(
  562. "{}/{}".format(output_path, _date_folder)
  563. ):
  564. # print(goods_art_no_folder)
  565. all_original_images = os.listdir(
  566. "{}/{}/{}/原始图".format(
  567. output_path, _date_folder, goods_art_no_folder
  568. )
  569. )
  570. all_moved_images = [
  571. os.path.splitext(x)[0]
  572. for x in os.listdir(
  573. "{}/{}/{}/原始图_已抠图".format(
  574. output_path, _date_folder, goods_art_no_folder
  575. )
  576. )
  577. ]
  578. for file in all_original_images:
  579. if os.path.splitext(file)[0] not in all_moved_images:
  580. print("----------》", goods_art_no_folder, file)
  581. to_do_images_total += 1
  582. if to_do_images_total > 0:
  583. self.progress_sign.emit(
  584. {"type": "处理图片 抠图、加工等", "progress_bar_value": 0}
  585. )
  586. else:
  587. return True
  588. """开始处理抠图等处理"""
  589. n = 0
  590. for _date_folder in os.listdir(output_path):
  591. # 过滤非文件夹的文件
  592. if not os.path.isdir("{}/{}".format(output_path, _date_folder)):
  593. continue
  594. # 扫描每个货号
  595. for goods_art_no_folder in os.listdir(
  596. "{}/{}".format(output_path, _date_folder)
  597. ):
  598. all_original_images = os.listdir(
  599. "{}/{}/{}/原始图".format(
  600. output_path, _date_folder, goods_art_no_folder
  601. )
  602. )
  603. all_moved_images = [
  604. os.path.splitext(x)[0]
  605. for x in os.listdir(
  606. "{}/{}/{}/原始图_已抠图".format(
  607. output_path, _date_folder, goods_art_no_folder
  608. )
  609. )
  610. ]
  611. for file in all_original_images:
  612. original_image_path = "{}/{}/{}/原始图/{}".format(
  613. output_path, _date_folder, goods_art_no_folder, file
  614. )
  615. file_name = os.path.splitext(file)[0]
  616. if file_name not in all_moved_images:
  617. print("上传平台获取抠图结果----------》", file)
  618. goods_art_no_folder_path = "{}/{}/{}".format(
  619. output_path, _date_folder, goods_art_no_folder
  620. )
  621. pic_deal = PicDeal()
  622. # 上传平台获取抠图结果
  623. original_move_bg_image_path = "{}/原始图_已抠图/{}{}".format(
  624. goods_art_no_folder_path, file_name, ".png"
  625. )
  626. if pic_deal.remove_bg(
  627. in_path=original_image_path,
  628. out_path=original_move_bg_image_path,
  629. ):
  630. self.show_progress_detail(
  631. "货号图{} 已完成抠图处理~".format(file_name)
  632. )
  633. # 抠图处理成白底图 800*800
  634. out_800_path = "{}/800x800/{}{}".format(
  635. goods_art_no_folder_path, file_name, ".jpg"
  636. )
  637. pic_deal.create_800image(
  638. image_path=original_move_bg_image_path,
  639. out_path=out_800_path,
  640. )
  641. # 抠图处理成白底图 200*200
  642. out_200_path = "{}/200images/{}{}".format(
  643. goods_art_no_folder_path, file_name, ".jpg"
  644. )
  645. pic_deal.resize_and_save(
  646. image_path=out_800_path,
  647. out_path=out_200_path,
  648. width=200,
  649. )
  650. self.show_progress_detail(
  651. "货号图{} 已完成800*800图片和200*200图片制作~".format(
  652. file_name
  653. )
  654. )
  655. else:
  656. self.show_progress_detail(
  657. "货号图{} 抠图处理失败~".format(file_name)
  658. )
  659. # 完成处理的图片进度
  660. n += 1
  661. self.progress_sign.emit(
  662. {
  663. "type": "处理图片 抠图、加工等",
  664. "progress_bar_value": int(n / to_do_images_total * 100),
  665. }
  666. )
  667. def create_folder(self, path):
  668. def check_folder(__path):
  669. if not os.path.exists(__path):
  670. os.makedirs(__path)
  671. return False
  672. return True
  673. # 文件夹不存在,创建货号子集文件夹
  674. if not check_folder(path):
  675. for name in ["原始图", "原始图_已抠图", "800x800", "200images"]:
  676. other_path = path + "/" + name
  677. check_folder(other_path)
  678. def get_date_time_original(self, file_path):
  679. with open(file_path, "rb") as file_data:
  680. tags = exifread.process_file(file_data)
  681. if "EXIF DateTimeOriginal" in tags:
  682. return str(tags["EXIF DateTimeOriginal"])
  683. else:
  684. return False
  685. class TempItem(QWidget):
  686. select_sign = Signal(str)
  687. def __init__(self, parent, _id, image_path):
  688. super().__init__(parent)
  689. self.ui = UI_temp_item()
  690. self.ui.setupUi(self)
  691. self.image_path = image_path
  692. self.id = _id
  693. self.is_select = False
  694. self.init()
  695. def init(self):
  696. self.ui.label.mousePressEvent = self.pic_show
  697. self.ui.radioButton.clicked.connect(self.select)
  698. self.set_label_image()
  699. def cancel_select(self, *args):
  700. self.is_select = False
  701. self.ui.radioButton.setChecked(False)
  702. def select(self, *args):
  703. self.is_select = True
  704. self.ui.radioButton.setChecked(True)
  705. self.select_sign.emit(self.id)
  706. def pic_show(self, *args, **kwargs):
  707. if os.path.exists(self.image_path):
  708. im = Image.open(self.image_path)
  709. threading.Thread(target=im.show, args=()).start()
  710. def set_label_image(self):
  711. if not os.path.exists(self.image_path):
  712. return
  713. try:
  714. bytes_io = io.BytesIO()
  715. w, h = self.ui.image_show.width(), self.ui.image_show.height()
  716. _img_raw = Image.open(self.image_path)
  717. _img_raw = self.to_resize(_img_raw, width=w * 2)
  718. _img_raw = _img_raw.crop(box=(0, 0, w * 2, h * 2))
  719. # _img_raw.thumbnail((w * 2, int(_img_raw.height * w * 2 / _img_raw.width)))
  720. # img_raw = _img_raw.resize(size=(w, h))
  721. _img_raw.save(bytes_io, "JPEG")
  722. icon = QPixmap()
  723. # icon.loadFromData(img)
  724. icon.loadFromData(bytes_io.getvalue())
  725. icon = icon.scaled(
  726. self.ui.image_show.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation
  727. )
  728. self.ui.image_show.setPixmap(icon)
  729. # self.mousePressEvent = lambda x: self.show_one_data(row)
  730. except:
  731. pass
  732. def to_resize(self, _im, width=None, high=None):
  733. _im_x, _im_y = _im.size
  734. if width and high:
  735. if _im_x >= _im_y:
  736. high = None
  737. else:
  738. width = None
  739. if width:
  740. re_x = int(width)
  741. re_y = int(_im_y * re_x / _im_x)
  742. else:
  743. re_y = int(high)
  744. re_x = int(_im_x * re_y / _im_y)
  745. _im = _im.resize((re_x, re_y))
  746. return _im