【阿里云】图像识别 智能分类识别 项目开发(一)

语音模块和阿里云图像识别结合
环境准备
代码实现
编译运行
写个shell脚本用于杀死运行的进程

语音模块和阿里云图像识别结合

使用语音模块和摄像头在香橙派上做垃圾智能分类识别

语音控制摄像下载上传阿里云解析功能点实现

环境准备

  1. 将语音模块接在UART5的位置

  2. 在orange pi 3.0.6上确认已经配置开启了uart5:(overlays=uart5)

bash 复制代码
cat /boot/orangepiEnv.txt
  1. 同时将USB摄像头接到香橙派上

  2. 确认已经运行了mjpg-streamer服务

bash 复制代码
ps ax | grep mjpg_streamer | grep -v grep

代码实现

main.c

c 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#include "uartTool.h"
#include "garbage.h"

 // 判断进程是否在运行
static int detect_process(const char * process_name)
{
	int n = -1;
	FILE *strm;
	char buf[128] = {0};
	
	// 构造命令字符串,通过ps命令查找进程
	sprintf(buf, "ps -ax | grep %s|grep -v grep", process_name);
	// 使用popen执行命令并读取输出
	if ((strm = popen(buf, "r")) != NULL) {
		if (fgets(buf, sizeof(buf), strm) != NULL) {
			n = atoi(buf); // 将进程ID字符串转换为整数
		}
	}
	else {
		return -1; // popen失败
	}	
	pclose(strm); // 关闭popen打开的文件流

	return n;
}

int main(int argc, char *argv[])
{
	int serial_fd = -1;
	int ret = -1;
	unsigned char buffer[6] = {0xAA, 0X55, 0x00, 0x00, 0x55, 0xAA};
	int len = 0;
	char *category = NULL;

	// 初始化串口和垃圾分类模块
	garbage_init ();

	// 用于判断mjpg_streamer服务是否已经启动
	ret = detect_process ("mjpg_streamer");

	if (-1 == ret) {
		printf("detect process failed\n");
        goto END;
	}
	
	// 打开串口
	serial_fd = my_serialOpen (SERIAL_DEV, BAUD);

	if (-1 == serial_fd) {
		goto END;
	}

	while (1) {
		// 从串口读取数据
		len = my_serialGetstring (serial_fd, buffer);
		printf("lend = %d, buf[2] = 0x%x\n", len, buffer[2]);
		
		if (len > 0 && buffer[2] == 0x46) {
			buffer[2] = 0x00;

			// 在执行wget命令之前添加调试输出
			printf("Executing wget command...\n");
			// 使用系统命令拍照
			system(WGET_CMD);
			// 在执行wget命令之后添加调试输出
			printf("Wget command executed.\n");
			
			// 判断垃圾种类
			if (0 == access(GARBAGE_FILE, F_OK)) {
				category = garbage_category (category);
				if (strstr(category, "干垃圾")) {
					buffer[2] = 0x41;
				}
				else if (strstr(category, "湿垃圾")) {
					buffer[2] = 0x42;
				}
				else if (strstr(category, "可回收垃圾")) {
					buffer[2] = 0x43;
				}
				else if (strstr(category, "有害垃圾")) {
					buffer[2] = 0x44;
				}
				else {
					buffer[2] = 0x45; //未识别到垃圾类型
				}
			}
			else {
                buffer[2] = 0x45; //识别失败
            }
			// 发送分类结果到串口
			my_serialSendstring (serial_fd, buffer, 6);
			buffer[2] = 0x00;
			remove(GARBAGE_FILE); // 删除拍照文件
		}
	}
END:
	// 释放垃圾分类资源
	garbage_final();

	return 0;
}

garbage.py

python 复制代码
# garbage.py
# -*- coding: utf-8 -*-
# 引入依赖包
# pip install alibabacloud_imagerecog20190930

import os
import io
from urllib.request import urlopen
from alibabacloud_imagerecog20190930.client import Client
from alibabacloud_imagerecog20190930.models import ClassifyingRubbishAdvanceRequest
from alibabacloud_tea_openapi.models import Config
from alibabacloud_tea_util.models import RuntimeOptions

config = Config(
  # 创建AccessKey ID和AccessKey Secret,请参考https://help.aliyun.com/document_detail/175144.html。
  # 如果您用的是RAM用户的AccessKey,还需要为RAM用户授予权限AliyunVIAPIFullAccess,请参考https://help.aliyun.com/document_detail/145025.html
  # 从环境变量读取配置的AccessKey ID和AccessKey Secret。运行代码示例前必须先配置环境变量。
  access_key_id=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
  access_key_secret=os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
  # 访问的域名
  endpoint='imagerecog.cn-shanghai.aliyuncs.com',
  # 访问的域名对应的region
  region_id='cn-shanghai'
)

def alibaba_garbage():
  # 场景一:文件在本地
  img = open(r'/tmp/garbage.jpg', 'rb')
  # 场景二:使用任意可访问的url
  # url = 'https://viapi-test-bj.oss-cn-beijing.aliyuncs.com/viapi-3.0domepic/imagerecog/ClassifyingRubbish/ClassifyingRubbish1.jpg'
  # img = io.BytesIO(urlopen(url).read())
  classifying_rubbish_request = ClassifyingRubbishAdvanceRequest()
  classifying_rubbish_request.image_urlobject = img
  runtime = RuntimeOptions()
  try:
    # 初始化Client
    client = Client(config)
    response = client.classifying_rubbish_advance(classifying_rubbish_request, runtime)
    # 获取整体结果
    # print(response.body)
    # 打印并返回需要的结果
    print(response.body.to_map()['Data']['Elements'][0]['Category'])
    return response.body.to_map()['Data']['Elements'][0]['Category']
  except Exception as error:
    # 获取整体报错信息
    # print(error)
    print(type('获取失败'))
    return '获取失败'
    # 获取单个字段
    # print(error.code)

if __name__ == "__main__":
  alibaba_garbage()

garbage.h

c 复制代码
#ifndef __GARBAGE__H
#define __GARBAGE__H

void garbage_init();
void garbage_final();
char *garbage_category(char *category);

// 增加拍照指令和照片路径宏定义
#define WGET_CMD "wget http://127.0.0.1:8080/?action=snapshot -O /tmp/garbage.jpg"
#define GARBAGE_FILE "/tmp/garbage.jpg"

#endif

garbage.c

c 复制代码
#include <stdio.h>
#include <Python.h>
#include "garbage.h"

void garbage_init()
{
    // 初始化Python解释器
    Py_Initialize();

    // 获取sys.path对象
    PyObject* sysPath = PySys_GetObject("path");

    // 将当前路径添加到sys.path中
    PyList_Append(sysPath, PyUnicode_DecodeFSDefault(".")); // PyUnicode_FromString将c字符串转换成Python字符串
}

void garbage_final()
{
    // 关闭Python解释器
    Py_Finalize();
}

char *garbage_category(char *category) 
{
    // 导入Python模块
    PyObject* pModule = PyImport_ImportModule("garbage");

    if (pModule != NULL) {
        // 获取Python函数对象
        PyObject* pFunction = PyObject_GetAttrString(pModule, "alibaba_garbage");

        if (pFunction != NULL && PyCallable_Check(pFunction)) {
            // 调用Python函数,这里是无参数调用
            PyObject* pArgs = PyTuple_New(0);  // 传递空参数元组
            PyObject* pResult = PyObject_CallObject(pFunction, pArgs);

            if (pResult != NULL) {
              // 将返回值转换为C类型
              char *result = NULL;
  
              if (!PyArg_Parse(pResult, "s", &result)) {
                PyErr_Print();
                printf("Error: parse failed\n");
              }
  
                // 打印返回值
                printf("pResult = %s\n", result);
                
                // 为垃圾分类信息分配内存,复制返回值
                category = (char *)malloc(sizeof(char) * (strlen(result) + 1));
                memset(category, 0, (strlen(result) + 1));
                strncpy(category, result, (strlen(result) + 1));
                 
                Py_DECREF(pResult);
            } else {
                PyErr_Print(); // 打印Python错误信息
            }

            Py_DECREF(pFunction);
            Py_DECREF(pArgs);
        } else {
            PyErr_Print();
        }

        Py_DECREF(pModule);
    } else {
        PyErr_Print();
    }
    return category;
}

uartTool.h

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "wiringSerial.h"

#ifndef __UARTTOOL_H
#define __UARTTOOL_H

int my_serialOpen (const char *device, const int baud) ;

void my_serialSendstring (const int fd, const unsigned char *s, int len) ;

int my_serialGetstring (const int fd, unsigned char *buffer) ;

#define SERIAL_DEV "/dev/ttyS5"
#define BAUD 115200

#endif

uartTool.c

c 复制代码
#include "wiringSerial.h"
#include "uartTool.h"

int my_serialOpen (const char *device, const int baud)
{
	struct termios options ;   // 创建一个termios结构体,用于串口参数设置
	speed_t myBaud ;   // 创建一个速度类型的变量 myBaud,用于保存波特率
	int status, fd ;   // 创建整数类型的变量 status 和 fd,用于保存状态和文件描述符
 
	switch (baud){   // 根据传入的波特率参数选择合适的波特率常数
		case   9600: myBaud =   B9600 ; break ; 
		case 115200: myBaud = B115200 ; break ; 
	}
	if ((fd = open (device, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK)) == -1)   // 打开串口设备,设置打开选项
	return -1 ;   // 如果打开失败,返回错误代码 -1
	
	fcntl (fd, F_SETFL, O_RDWR) ;   // 设置文件状态标志
	
// Get and modify current options: 获取并修改当前的串口参数:
 
	tcgetattr (fd, &options) ;   // 获取当前的串口参数
 
	cfmakeraw (&options) ;   // 初始化 termios 结构体为原始模式
	cfsetispeed (&options, myBaud) ;  // 设置输入波特率
    cfsetospeed (&options, myBaud) ;  // 设置输出波特率
 
    options.c_cflag |= (CLOCAL | CREAD) ;  // 本地连接和使能接收
    options.c_cflag &= ~PARENB ;  // 禁用奇偶校验
    options.c_cflag &= ~CSTOPB ;  // 1位停止位
    options.c_cflag &= ~CSIZE ;  // 用数据位掩码清空数据位设置
    options.c_cflag |= CS8 ;  // 设置8位数据位
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;   // 禁用规范输入
	options.c_oflag &= ~OPOST ;   // 禁用输出处理
 
	options.c_cc [VMIN] = 0 ;   // 读取数据的最小字符数
	options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds) 超时等待时间(十分之一秒100ms)
 
	tcsetattr (fd, TCSANOW, &options) ;   // 设置新的串口参数
 
	ioctl (fd, TIOCMGET, &status);   // 获取串口控制模式状态
 
	status |= TIOCM_DTR ;   // 设置 DTR(数据终端就绪)位
	status |= TIOCM_RTS ;   // 设置 RTS(请求发送)位
 
	ioctl (fd, TIOCMSET, &status);   // 设置串口控制模式状态
	
	usleep (10000) ;  // 暂停 10 毫秒
	
	return fd ;   // 返回串口文件描述符
}

void my_serialSendstring (const int fd, const unsigned char *s, int len)
{
	int ret ;

	ret = write (fd, s, len) ; 
	
	if (ret < 0) 
		printf ("Serial Sendstring Error\n") ;
}

int my_serialGetstring (const int fd, unsigned char *buffer)
{
	int n_read ;

	n_read = read (fd, buffer, 32) ; 
	
	return n_read ;
}

编译运行

bash 复制代码
编译 
gcc -o test *.c *.h -I /usr/include/python3.10 -l python3.10

执行 
sudo -E ./test
sudo -E 命令用于在以超级用户权限运行命令的同时,保留环境变量

查看进程 
ps -ax | grep mjpg_streamer | grep -v grep
ps -ax | grep ./test | grep -v grep
ps aux | grep './test' | grep -v grep | awk '{print $2}'

杀死进程 
kill -9 pid (-9-------SIGKILL)


写个shell脚本用于杀死运行的进程

当你运行程序时,shell脚本可以使用ps命令查找到特定进程的PID并使用kill命令杀死该进程。

以下是一个简单的Shell脚本示例,假设你的程序名为test

bash 复制代码
#!/bin/bash

# 查找进程PID
PID=$(ps aux | grep './test' | grep -v grep | awk '{print $2}')

if [ -n "$PID" ]; then
    # 杀死进程
    kill -SIGKILL $PID
    echo "Process ./test (PID $PID) killed."
else
    echo "Process ./test not found."
fi

这个脚本中,ps aux命令获取当前所有进程的信息,grep './test'用于查找包含"./test"的进程,awk '{print $2}'用于提取PID。然后,脚本检查是否找到了进程,如果找到,就使用kill命令杀死进程,并输出相关信息。如果没有找到对应进程,输出相应的提示。

grep -v grep 是为了在使用 ps 命令结合 grep 进行进程查询时,排除掉 grep 进程本身。当你执行 ps aux | grep 'test' 时,该命令本身也会被匹配,因为它包含了关键字 'test'。为了排除掉这个匹配,使用 grep -v grep 来过滤掉含有 'grep' 字符串的行,从而得到准确的进程信息。

将这个脚本保存为kill_test.sh,并添加执行权限:

bash 复制代码
chmod +x kill_test.sh

然后可以通过运行./kill_test.sh来执行脚本。确保在运行脚本之前你的程序已经启动。

相关推荐
思则变3 小时前
[Pytest] [Part 2]增加 log功能
开发语言·python·pytest
漫谈网络3 小时前
WebSocket 在前后端的完整使用流程
javascript·python·websocket
try2find4 小时前
安装llama-cpp-python踩坑记
开发语言·python·llama
博观而约取5 小时前
Django ORM 1. 创建模型(Model)
数据库·python·django
精灵vector7 小时前
构建专家级SQL Agent交互
python·aigc·ai编程
Zonda要好好学习7 小时前
Python入门Day2
开发语言·python
Vertira7 小时前
pdf 合并 python实现(已解决)
前端·python·pdf
太凉7 小时前
Python之 sorted() 函数的基本语法
python
项目題供诗7 小时前
黑马python(二十四)
开发语言·python
晓13138 小时前
OpenCV篇——项目(二)OCR文档扫描
人工智能·python·opencv·pycharm·ocr