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()