Умная сортировка мусора
9 апреля 2021 года в провинции Чжэцзян состоялось 7-е соревнование по инженерной подготовке.Наша группа участвовала в проекте по классификации мусора.Наша группа успешно вышла в финал, но мы увидели, что в правилах финала не отмечены различные классификации мусора, и мы не были полностью подготовлены.Чтобы иметь дело с различными классификации мусора, поэтому национальный конкурс пропущен!
предисловие
С непрерывным развитием искусственного интеллекта технология машинного обучения становится все более и более важной.Многие люди начали изучать машинное обучение.Эта статья знакомит с основным содержанием машинного обучения посредством конкурса и дизайном интерфейса, необходимым для участия в конкурсе. . Правила наших предварительных занятий таковы, но меня немного смущает отображение названий мусора. Лучше разделить их на четыре типа мусора. С какой целью различать листья овощей и апельсиновые корки?Позвольте мне сначала представиться, я второкурсник компьютерных наук и технологий, и двое моих товарищей по команде, и я участвовал в 7-м соревновании по инженерной подготовке, Мои задачи в команде - обработка изображений, обучение модели и связь и интерфейс последовательного порта stm322F4. дизайн, поэтому я в основном буду говорить о коде, который я реализовал, я не очень хорошо, надеюсь на понимание!
Мусор такой, когда мы играем!
(1) Подготовка к установке программного обеспечения
Эти загрузки программного обеспечения доступны в разделе программного обеспечения. Вы можете зайти в общедоступную учетную запись WeChat, чтобы обратить внимание. Этапы загрузки действительно подробны! !Я установил Anaconda pycharm python3.6 (версия не должна быть слишком высокой) Программное обеспечение для проектирования интерфейса Qt
Скачать tensflow через python3.6
Загрузка других различных библиотек требует, чтобы вы сначала создали среду, а затем загрузили ее из следующего места в pycharm.
Формат: pip install numpy (в качестве примера возьмем numpy)Мы используем ноутбук для обучения, а затем обучаем модель и помещаем ее в микрокомпьютер win10 для отображения рабочего интерфейса (примечание: тренажер должен быть хорошим!!! Условия допускают прямой доступ к настольному компьютеру)
(2) Модель обучения классификации мусора
Во-первых, файл, в котором я показываю окончательный код для моего конкурса, выглядит следующим образом.Потом смотрим на сам вопрос классификации мусора, вроде бы хорошо разобрались, то есть различать мусор, но как этого добиться? Направления может и не быть вовсе. Тогда будет намного быстрее начать прямо с вышеуказанного файла.
Точно так же, как мы классифицируем предметы, это процесс повторного обучения. Но что самое основное? Это наша способность учиться, это основа программной модели
Первый файл .py — это модель обучения, фреймворк использует модель реснета в keras, а затем мы обучаем эту модель в целевую модель, специализирующуюся на распознавании изображений.
Это тренировочный набор, который заключается в том, чтобы в папку dataset1 класть картинки (я классифицировал их на 10 типов по 420 картинок в каждой) для обучения, но если позволяют аппаратные условия, то чем больше картинок, тем лучше.
Но обратите особое внимание на то, чтобы изображения не имели китайского пути, а номер файла каждого изображения был максимально одинаковым.
# 处理好的224*224文件夹放在本程序同目录下...
train_path_A = './dataset1/train/A/'
train_path_B = './dataset1/train/B/'
train_path_C = './dataset1/train/C/'
train_path_D = './dataset1/train/D/'
train_path_E = './dataset1/train/E/'
train_path_F = './dataset1/train/F/'
train_path_G = './dataset1/train/G/'
train_path_H = './dataset1/train/H/'
train_path_I = './dataset1/train/I/'
train_path_J = './dataset1/train/J/'
mglist_train_A = os.listdir(train_path_A) #导入训练列表
imglist_train_B = os.listdir(train_path_B)
imglist_train_C = os.listdir(train_path_C)
imglist_train_D = os.listdir(train_path_D)
imglist_train_E = os.listdir(train_path_E)
imglist_train_F = os.listdir(train_path_F)
imglist_train_G = os.listdir(train_path_G)
imglist_train_H = os.listdir(train_path_H)
imglist_train_I = os.listdir(train_path_I)
imglist_train_J = os.listdir(train_path_J)
Здесь определены два объекта numpy: входной массив X_test и массив меток Y_test, а np.empty создает пустой многомерный массив. 3 - количество каналов картинки (RGB три цвета) Поскольку есть десять видов изображений, второй элемент Y_train() установлен на 10.
X_train = np.empty((len(imglist_train_A) + len(imglist_train_B) + len(imglist_train_C) + len(imglist_train_D) + len(imglist_train_E)
+ len(imglist_train_F) + len(imglist_train_G) + len(imglist_train_H) + len(imglist_train_I) + len(imglist_train_J), 224, 224, 3))
Y_train = np.empty((len(imglist_train_A) + len(imglist_train_B) + len(imglist_train_C) + len(imglist_train_D) + len(imglist_train_E)
+ len(imglist_train_F) + len(imglist_train_G) + len(imglist_train_H) + len(imglist_train_I) + len(imglist_train_J), 10))
Обученная модель сохраняется на следующей модели
#保存变量训练文件.h5
model.save('my_resnet_model_ABCD.h5')
model.save_weights('my_resnet_weights_model_ABCD.h5') #保存变量训练文件
#载入变量训练文件.h5
model = tf.keras.models.load_model('my_resnet_model_ABCD.h5')
model.load_weights('my_resnet_weights_model_ABCD.h5')
Если вы измените тип обучения данных, эти параметры должны быть изменены соответствующим образом.Данные, на которые указывает стрелка, должны быть просмотрены.Комментарии очень подробные, то есть размер_пакета предпочтительно является четным числом.
Модель обучения доступна, но мы хотим, чтобы она давала нам точное значение обратной связи. В настоящее время нам нужен тестовый набор. Соотношение изображений обучающего набора и тестового набора составляет около 10: 3.
# 预测:predict(img)
for i in range(10):
img=X_test[i] #在数据集上取得一个样本
print('某个测试图片X_test[i]的形态:', img.shape)
img=(np.expand_dims(img,0)) #表示在0位置添加一个维度数据[[[...],[...],[...],...,[...]]]
# tf.keras 模型输入形态要增加一个维度(1,28,28)
print('某个测试图片数据形态:',img.shape)
predictions=model.predict(img)
#看下第0项图片样本的预测结果是什么
print('模型预测结果predictions[i]:',predictions)
#第0项图片预测最大的概率项是哪一项,就是说最可能是哪种衣服
print('模型预测最大的概率项:',np.argmax(predictions))
#再查询第0项图片真正的标签是什么样的
print('查询第i项图片真正的标签是:',Y_test[i])
#显示一个图片:
plt.figure()
plt.imshow(X_test[i])
plt.colorbar()
plt.grid(False)
plt.show()
(3) Дизайн интерфейса Qt
Когда я занимался дизайном интерфейса, я старался расположить контент в соответствии с размером экрана дисплея, чтобы контент был относительно компактным, а зеленый фон нетрудно представить, что связано с этой темой.
Как отобразить текст в textedit, как вызвать кнопку?
# 在各个write_ui...的界面textEdit...中写入str
self.ms.text_print1.connect(self.write_ui1)
self.ms.text_print2.connect(self.write_ui2)
self.ms.text_print3.connect(self.write_ui3)
self.ms.text_print4.connect(self.write_ui4)
self.ms.text_print5.connect(self.write_ui5)
# 初始化线程参数
self.ui.pushButton.clicked.connect(self.handlePlay) # 播放
self.ui.pushButton_2.clicked.connect(self.handleCircle) # 循环播放
self.ui.pushButton_7.clicked.connect(self.handleStopPlay) # 停止播放
self.ui.pushButton_3.clicked.connect(self.handleStart) # 检测开始
self.ui.pushButton_4.clicked.connect(self.handleStop2) # 检测停止
self.ui.pushButton_5.clicked.connect(self.handleShow) # 显示图像
self.ui.pushButton_6.clicked.connect(self.handleQuit) # 关闭图像
# 在各个textEdit...控件上写入字符
def write_ui1(self, str1):
self.ui.textEdit.append(str1 + '\n') # 在textEdit写入str
def write_ui2(self, str2):
self.ui.textEdit_2.append(str2 + '\n') # 在textEdit_2写入str
def write_ui3(self, str3):
self.ui.textEdit_3.append(str3 + '\n') # 在textEdit_3写入str
def write_ui4(self, str4):
self.ui.textEdit_4.append(str4 + '\n') # 在textEdit_4写入str
def write_ui5(self, str5):
self.ui.textEdit_5.append(str5 + '\n') # 在textEdit_5写入str
Так как же работает циклическое воспроизведение и остановка воспроизведения? Я прекращаю играть, нажимая кнопку, чтобы зациклить и закрыть флаг, код выглядит следующим образом
# 循环播放
def handleCircle(self):
global ThreadFlag1 # 全局变量
ThreadFlag1 = 0
for i in range(20):
j = 0
cap = cv2.VideoCapture('./refuse classification video.mp4')
while (cap.isOpened()): # cap.grab()下一帧是否为空
info = ''
info += f'\t-- 垃圾回收宣传片循环播放 --\n'
self.ms.text_print1.emit(info) # 在textEdit写入str1
ret, frame = cap.read()
cv2.imshow('refuse classification video.mp4', frame)
j += 1
if (j == 835): # 防止视频最后的空帧报错
break
# 停止宣传片
if (ThreadFlag1 == 1):
self.ms.text_print1.emit(f'\t-- 垃圾回收宣传片停止播放 --\n')
break
k = cv2.waitKey(20)
# 关闭窗口
cap.release()
cv2.destroyAllWindows() # 删除视频窗口
# 停止播放
def handleStopPlay(self):
global ThreadFlag1 # 全局变量
if(ThreadFlag1==0&cap.isOpened()):
ThreadFlag1 = 1
В то время, за несколько недель до игры, я хотел включить камеру, чтобы увидеть окружение в мусорном баке, потому что верхняя часть нашего мусорного бака представляет собой черный ящик, так что смотреть напрямую не так-то просто.
# 显示图像
def handleShow(self):
global ThreadFlag3 # 全局变量
ThreadFlag3 = 0
self.ms.text_print3.emit(f' -- 摄像头打开,请投放垃圾! --\n')
while 1:
# get a frame
ret, frame = cap.read()
# show a frame
cv2.imshow("capture", frame)
if ThreadFlag3 == 1:
# 关闭窗口
cv2.destroyAllWindows() # 删除视频窗口
self.ms.text_print3.emit(f' -- 摄像头已经关闭,开始识别! --\n')
break
cv2.waitKey(1)
# 关闭图像
def handleQuit(self):
global ThreadFlag3 # 全局变量
if ThreadFlag3 == 0:
ThreadFlag3 = 1
Затем мы завершаем распознавание изображения, принимая передачу с последовательного порта? Когда начинать передачу информации на нижний ЭБУ, поворот рулевого механизма и мусорного ведра
# 接收串口数据
def handleRecv(self):
global final
global no
global ThreadFlag2 # 全局变量
ThreadFlag2 = 0
ser.flushInput() # 先清除一下缓冲区
ser.flushInput()
def download():
while 1:
self.ms.text_print2.emit(f'\t-- 接收到串口数据 --\n')
mcu = ser.read(1) ## 读取1个数据
mcu = ser.read(1) ## 读取1个数据
mcu = ser.read(1) ## 读取1个数据
mcu = ser.read(1) ## 读取1个数据
mcu = ser.read(1) ## 读取1个数据
print("接收到第一个数据:", mcu)
self.ms.text_print2.emit(f"\t-- 接收到数据:" + str(mcu))
if mcu == b'5': # 若收到下位机发送的数据/字符,
self.ms.text_print2.emit(f'\t-- 开始拍照 --')
mcu = '' # 清空数据
mcu = '' # 清空数据
mcu = '' # 清空数据
frameone,frame = cap.read() # 读取摄像头
# cv2.imshow("capture", frame) # 显示照片
cv2.waitKey(1) # 等0.1秒
cv2.imwrite("D:\\project_garbage\\picture\\0.jpg", frame) # 保存图片,自己新建个picture文件夹
self.ms.text_print2.emit(f'\t-- 保存照片 --')
self.predict() # 进入预测函数
Наконец, мы начинаем предсказывать реализацию распознавания изображений.
Я столкнулся с большим количеством проблем, когда делал этот дизайн интерфейса, я расскажу вам об этом здесь
Первый вопросЭто разница между 0 и 1, как показано на рисунке.
0 означает, что сам дисплей компьютера не имеет камеры, а использует периферийную камеру для съемки.
1 Относится, например, к портативному компьютеру, который сам имеет камеру и может переключаться между собственной камерой и периферийной камерой.
Я так и не обнаружил эту проблему во время отладки микрокомпьютера, это заняло у меня некоторое время
второй вопросэто путь, по которому импортируется изображение, стоит обратить внимание на разницу /\ Импорт изображений, чтение изображений
cv2.imwrite("D:\\project_garbage\\picture\\0.jpg", frame) # 保存图片,自己新建个picture文件夹
img_path = "D:/project_garbage/picture/0.jpg"
третий вопросКак показано на рисунке, последовательный порт не может принимать данные при передаче данных.Существует много типов этой проблемы, которые можно решить с помощью Baidu.Мы используем python для связи с компьютером нижнего положения MCU 32. Добавление \r\n в конце имеет решающее значение
Суммировать
Памятное подготовительное видео
Несмотря на то, что 7-е соревнование по инженерной подготовке не смогло пройти квалификацию национального соревнования, сцена совместной борьбы членов нашей команды в лаборатории до сих пор жива в моей памяти. Я думаю, что это воспоминание очень ценно. Мы много работали вместе! боролся! Думаю, оно того стоит.Дружба вне конкуренции бывает очень редко!
Прежде всего, я хотел бы поделиться тем, что в ночь перед игрой охранял наш детский мусорный бак в лабораторном здании (два товарища по команде)
Далее позвольте мне поделиться некоторыми фотографиями нашей поездки в залив Нинбо Ханчжоу.Мне очень нравится книга о птичьем гнезде из Технологического института Нинбо!
Это перед игрой, когда особенно сильный ветер, мои товарищи по команде фотографируют, я переучиваю модель, и дарю свою мусорку, полную тайн! !
В конце оставьте сертификат, это память!!!