From c076e04f572280d42c36b707e1d5cd7ece87f60a Mon Sep 17 00:00:00 2001 From: "li.zhenye" Date: Thu, 11 Aug 2022 17:34:40 +0800 Subject: [PATCH] =?UTF-8?q?[ext]=20=E4=BF=AE=E6=94=B9transmit=E5=88=B0?= =?UTF-8?q?=E4=B8=80=E5=8D=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 53 +++++++++++++++++++++++++++++++++++ transmit.py | 80 ++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 111 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index fa87f18..18445a1 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ ## 如何进行模型训练和部署? 1. 项目当中需要包含`data`和`models`这两个文件夹,请下载到当前文件夹下,这是链接:[data](https://macrosolid-my.sharepoint.com/personal/feijinti_miaow_fun/_layouts/15/onedrive.aspx?id=%2Fpersonal%2Ffeijinti%5Fmiaow%5Ffun%2FDocuments%2FPycharmProjects%2Ftobacco%5Fcolor%2Fdata&ga=1), [models](https://macrosolid-my.sharepoint.com/:f:/g/personal/feijinti_miaow_fun/EiyBjWEX90JGn8S-e5Kh7N8B1GWvfvDcNbpleWDTwkDm1w?e=wyL4EF) + 2. 使用[01_dataset.ipynb](./01_dataset.ipynb) 进行数据集的分析文件格式需要设置为这种形式: ```text dataset @@ -14,11 +15,63 @@ ├── img1.bmp └── ... ``` + 3. 使用[02_classification.ipynb](./02_classification.ipynb)进行训练 + 4. 使用[03_data_update.ipynb](02_classification.ipynb)进行数据的更新与添加 + 5. 使用`main_test.py`文件进行读图测试 + 6. **部署**,复制`utils.py`、`models.py`、`main.py`、`models/`、`config.py`这5个文件或文件夹,运行main.py来提供预测服务。 +## 如何进行参数调节? + +所有的参数均位于项目文件夹下的`config.py`当中。 + +```python +class Config: + # 文件相关参数 + nRows, nCols, nBands = 256, 1024, 22 + nRgbRows, nRgbCols, nRgbBands = 1024, 4096, 3 + + # 需要设置的谱段等参数 + selected_bands = [127, 201, 202, 294] + bands = [127, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 294] + is_yellow_min = np.array([0.10167048, 0.1644719, 0.1598884, 0.31534621]) + is_yellow_max = np.array([0.212984, 0.25896924, 0.26509268, 0.51943593]) + is_black_threshold = np.asarray([0.1369, 0.1472, 0.1439, 0.1814]) + black_yellow_bands = [0, 2, 3, 21] + green_bands = [i for i in range(1, 21)] + + # 光谱模型参数 + blk_size = 4 # 必须是2的倍数,不然会出错 + pixel_model_path = r"./models/pixel_2022-08-02_15-22.model" + blk_model_path = r"./models/rf_4x4_c22_20_sen8_9.model" + spec_size_threshold = 3 # 光谱大小阈值 + + # rgb模型参数 + rgb_tobacco_model_path = r"models/tobacco_dt_2022-08-05_10-38.model" + rgb_background_model_path = r"models/background_dt_2022-08-09_16-08.model" + threshold_low, threshold_high = 10, 230 # 亮度最高值和最低值 + threshold_s = 190 # 饱和度最高值允许值,超过该饱和度会被当作杂质 + rgb_size_threshold = 4 # RGB大小阈值(在运行时会被界面修改) + + # mask parameter + target_size = (1024, 1024) # (Width, Height) of mask + valve_merge_size = 2 # 每两个喷阀当中有任意一个出现杂质则认为都是杂质 + valve_horizontal_padding = 3 # 喷阀横向膨胀的尺寸,应该是奇数,3时表示左右各膨胀1 + max_open_valve_limit = 25 # 最大同时开启喷阀限制,按照电流计算,当前的喷阀可以开启的喷阀 600W的电源 / 12V电源 = 50A, 一个阀门1A + + # save part + offset_vertical = 0 + + # logging + root_dir = os.path.split(os.path.realpath(__file__))[0] +``` + + + ## 训练的原理 为了应对工业环境当中负样本少的特点,我们结合颜色有限空间的特性对我们的训练过程进行了优化,核心的优化方式在于制造负样本。 diff --git a/transmit.py b/transmit.py index 2d3d29d..52971bf 100644 --- a/transmit.py +++ b/transmit.py @@ -1,7 +1,10 @@ +import multiprocessing import os import threading from multiprocessing import Process, Queue import time +from multiprocessing.synchronize import Lock +from threading import Lock import cv2 @@ -11,13 +14,15 @@ import functools import numpy as np from config import Config from models import SpecDetector, RgbDetector -from typing import Any +from typing import Any, Union import logging logging.basicConfig(format='%(asctime)s %(levelname)s %(name)s %(message)s', level=logging.WARNING) class Transmitter(object): + _io_lock: Union[Lock, Lock] + def __init__(self, job_name:str, run_process:bool = False): self.output = None self.job_name = job_name @@ -25,6 +30,7 @@ class Transmitter(object): self._thread_stop = threading.Event() self._thread_stop.clear() self._running_handler = None + self._io_lock = multiprocessing.Lock() if run_process else threading.Lock() def set_source(self, *args, **kwargs): """ @@ -35,13 +41,13 @@ class Transmitter(object): """ raise NotImplementedError - def set_output(self, output: ImgQueue): + def set_output(self, *args, **kwargs): """ - 设置单个输出源 + 设置输出源 :param output: :return: """ - self.output = output + raise NotImplementedError def start(self, *args, **kwargs): """ @@ -113,6 +119,44 @@ class BeforeAfterMethods: return rgb_img +class FileReceiver(Transmitter): + def __init__(self, job_name:str, input_dir: str, output_queue:ImgQueue, speed: int=3, name_pattern=None): + super(FileReceiver, self).__init__(job_name=job_name, run_process=False) + self.input_dir = input_dir + self.send_speed = speed + self.file_names = None + self.name_pattern = name_pattern + self.file_idx = 0 + self.output_queue = None + self.set_source(input_dir, name_pattern) + self.set_output(output_queue) + + def set_source(self, input_dir, name_pattern=None): + self.name_pattern = name_pattern if name_pattern is not None else self.name_pattern + file_names = os.listdir(input_dir) + if len(file_names) == 0: + logging.warning('指定了空的文件夹') + if self.name_pattern is not None: + file_names = [file_name for file_name in file_names if (self.name_pattern in file_name)] + else: + file_names = file_names + + with self._io_lock: + self.file_names = file_names + self.file_idx = 0 + + def set_output(self, output: ImgQueue): + with self._io_lock: + self.output_queue = output + + @Transmitter.job_decorator + def job_func(self, *args, **kwargs): + with self._io_lock: + self.file_idx += 1 + if self.file_idx == len() + file_name = self.file_names[self.file_idx] + + class FifoReceiver(Transmitter): def __init__(self, job_name:str, fifo_path: str, output: ImgQueue, read_max_num: int, msg_queue=None): @@ -169,31 +213,23 @@ class FifoSender(Transmitter): os.mkfifo(output_fifo_path, 0o777) self._output_fifo_path = output_fifo_path - def start(self, pre_process=None, name='fifo_receiver'): - self._running_thread = threading.Thread(target=self._send_thread_func, name=name, - args=(pre_process, )) - self._running_thread.start() - def stop(self): - self._need_stop.set() - - def _send_thread_func(self, pre_process=None): + def job_func(self, pre_process, *args, **kwargs): """ 接收线程 :param pre_process: :return: """ - while not self._need_stop.is_set(): - if self._input_source.empty(): - continue - data = self._input_source.get() - if pre_process is not None: - data = pre_process(data) - output_fifo = os.open(self._output_fifo_path, os.O_WRONLY) - os.write(output_fifo, data) - os.close(output_fifo) - self._need_stop.clear() + if self._input_source.empty(): + return + data = self._input_source.get() + if pre_process is not None: + data = pre_process(data) + output_fifo = os.open(self._output_fifo_path, os.O_WRONLY) + os.write(output_fifo, data) + os.close(output_fifo) + def __del__(self): self.stop()