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

语音模块和阿里云图像识别结合
环境准备
代码实现
编译运行
写个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来执行脚本。确保在运行脚本之前你的程序已经启动。

相关推荐
哇咔咔哇咔27 分钟前
【科普】conda、virtualenv, venv分别是什么?它们之间有什么区别?
python·conda·virtualenv
CSXB991 小时前
三十四、Python基础语法(文件操作-上)
开发语言·python·功能测试·测试工具
java知路1 小时前
阿里云aliyun gradle安装包下载地址
阿里云·云计算
GJCTYU1 小时前
阿里云多端低代码开发平台魔笔使用测评
低代码·阿里云·云原生·容器·serverless·云计算
CookieSAdam1 小时前
阿里云ECS服务器使用限制及不允许做的事情
阿里云·阿里云ecs
傲骄鹿先生1 小时前
阿里云centos7.9服务器磁盘挂载,切换服务路径
服务器·阿里云·磁盘
落樱坠入星野1 小时前
拿下阿里云之后如何在本地运行镜像进行分析
经验分享·安全·网络安全·阿里云·云计算
亚图跨际2 小时前
MATLAB和Python及R潜变量模型和降维
python·matlab·r语言·生物学·潜变量模型
IT古董2 小时前
【机器学习】决定系数(R²:Coefficient of Determination)
人工智能·python·机器学习
德育处主任Pro2 小时前
『Django』APIView基于类的用法
后端·python·django