随笔,很随的那种。
1.复习一下shell编程。幸狐mpi例程里面的build.sh更新下,在编译完成之后可以使用ADB自动上传自动运行,提升效率。具体添加的在make install后面。
Build.sh
#!/bin/bash
ROOT_PWD=$(cd "$(dirname $0)" && cd -P "$(dirname "$SOURCE")" && pwd)
if [ "$1" = "clean" ]; then
if [ -d "${ROOT_PWD}/build" ]; then
rm -rf "${ROOT_PWD}/build"
echo " ${ROOT_PWD}/build has been deleted!"
fi
if [ -d "${ROOT_PWD}/install" ]; then
rm -rf "${ROOT_PWD}/install"
echo " ${ROOT_PWD}/install has been deleted!"
fi
exit
fi
options=("luckfox_pico_rtsp_opencv"
"luckfox_pico_rtsp_opencv_capture"
"luckfox_pico_rtsp_retinaface"
"luckfox_pico_rtsp_retinaface_osd"
"luckfox_pico_rtsp_yolov5")
PS3="Enter your choice [1-${#options[@]}]: "
select opt in "${options[@]}"; do
if [[ -n "$opt" ]]; then
echo "You selected: $opt"
echo "你选择了: $opt"
src_dir="example/$opt"
if [[ -d "$src_dir" ]]; then
if [ -d ${ROOT_PWD}/build ]; then
rm -rf ${ROOT_PWD}/build
fi
mkdir ${ROOT_PWD}/build
cd ${ROOT_PWD}/build
cmake .. -DEXAMPLE_DIR="$src_dir" -DEXAMPLE_NAME="$opt"
make install
adb shell ./oem/usr/bin/RkLunch-stop.sh
adb shell rm -rf /mnt/sdcard/${opt}_demo/
adb push ${ROOT_PWD}/install/${opt}_demo /mnt/sdcard/
adb shell chmod +x /mnt/sdcard/${opt}_demo
adb shell ./mnt/sdcard/${opt}_demo/${opt}
else
echo "错误:目录 $src_dir 不存在!"
echo "Error: Directory $src_dir does not exist!"
fi
break
else
echo "Invalid selection, please try again."
echo "无效的选择,请重新选择。"
fi
done
2.交叉编译一下数据库sqlite,方便以后用。buildroot系统基于uclibc构建,注意不要使用glibc。
去官网下载sqlite-autoconf开头的源码,tar -zxvf解压,然后进行配置。参数可以这样借鉴
./configure CC=FULL_PATH_OF_SDK/luckfox-pico/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc --prefix=WHERE_YOU_WANT_TO_INSTALL --host=arm-rockchip830-linux-uclibcgnueabihf
3. 关于camke的示例,弄好之后cmake .制作makefile,接着make -j2 就ok了,至于install下次再学吧。copilot做小任务真好用。
cmake_minimum_required(VERSION 3.10)
# 项目信息
project(SQLiteTest)
# 设置交叉编译器,记得改FULL_PATH_OF_SDK
set(CMAKE_C_COMPILER FULL_PATH_OF_SDK/luckfox-pico/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc)
# 设置SQLite的路径,记得改YOUR_PREFIX_PATH
set(SQLITE_PREFIX YOUR_PREFIX_PATH/sqlite-autoconf-3470000/Build)
set(SQLITE_LIB ${SQLITE_PREFIX}/lib)
set(SQLITE_INC ${SQLITE_PREFIX}/include)
# 包含目录
include_directories(${SQLITE_INC})
# 添加可执行文件
add_executable(main main.c)
# 链接库
target_link_libraries(main ${SQLITE_LIB}/libsqlite3.a)
附上copilot的测试代码。

#include <stdio.h>
#include <sqlite3.h>
#include <assert.h>
// Function to test SQLite connection, create table, insert and read data
int testSQLite() {
sqlite3 *db;
char *errMsg = 0;
int rc;
const char *sql;
// Open database connection
rc = sqlite3_open(":memory:", &db);
if (rc) {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
return 0;
}
// Create SQL table
sql = "CREATE TABLE TEST (ID INT PRIMARY KEY NOT NULL, NAME TEXT NOT NULL);";
rc = sqlite3_exec(db, sql, 0, 0, &errMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", errMsg);
sqlite3_free(errMsg);
sqlite3_close(db);
return 0;
}
// Insert data into table
sql = "INSERT INTO TEST (ID, NAME) VALUES (1, 'Alice');";
rc = sqlite3_exec(db, sql, 0, 0, &errMsg);
if (rc != SQLITE_OK) {
fprintf(stderr, "SQL error: %s\n", errMsg);
sqlite3_free(errMsg);
sqlite3_close(db);
return 0;
}
// Read data from table
sql = "SELECT ID, NAME FROM TEST;";
sqlite3_stmt *stmt;
rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
if (rc != SQLITE_OK) {
fprintf(stderr, "Failed to fetch data: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 0;
}
while (sqlite3_step(stmt) == SQLITE_ROW) {
int id = sqlite3_column_int(stmt, 0);
const unsigned char *name = sqlite3_column_text(stmt, 1);
printf("ID: %d, Name: %s\n", id, name);
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return 1;
}
// Main function for running the test
int main() {
int result = testSQLite();
assert(result && "SQLite test failed");
printf("SQLite test passed\n");
return 0;
}
4. RTSP测试
Rk的RTSP是udp协议的,不知道是不是因为pc的原因,延迟很大很大。目前vlc在ubuntu上有bug,需要用ffmpeg去播放。ffplay rtsp://192.168.10.200/live/0
5.视频性能和帧率的测试
I. 造成10帧的罪魁祸首已经找到了,不是我当初认为的文件写入,而是opencv。只要是牵扯到opencv的解码和打字幕帧率直接暴降不到10帧。目前来看文件不是瓶颈,需要做的就是放弃opencv,使用rk官方加速的库和OSD。
II. 今天也尝试了一下使用opencv进行运动检测,帧率更是直接掉到1.5帧,这也是不可以接受的。(倒是内存还挺够用哈哈


III. rk官方的图像库是带有顺序和异步模式的,这个很值得研究。下一步就是阅读手册,尝试学会使用rk的图像库,再进行优化。另外看起来rk官方还提供了windows下的模拟器(vs2022的项目),可以模拟rk芯片的环境,使用高性能设备来降低开发的时间成本,可能能用上,再研究。
IV. 码力下降了,使用cpp的opencv有点眼花缭乱,还是要练习啊!贴上cpp版本的代码,算法的提供者为Renu Khandelwal,文章链接在这里https://towardsdev.com/motion-detection-within-a-boundary-using-opencv-bd430516957。
#include <opencv2/opencv.hpp>
#include <iostream>
int main() {
// 打开默认摄像头
cv::VideoCapture cap(0);
if (!cap.isOpened()) {
std::cerr << "Error: Could not open webcam." << std::endl;
return -1;
}
int frame_count = 0;
int motion = 0;
// 读取第一帧作为初始图像
cv::Mat Prev_frame;
cap >> Prev_frame;
if (Prev_frame.empty()) {
std::cerr << "Error: Could not read frame from webcam." << std::endl;
return -1;
}
cv::Mat Prev_frame_gray;
cv::cvtColor(Prev_frame, Prev_frame_gray, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(Prev_frame_gray, Prev_frame_gray, cv::Size(21, 21), 0);
while (cap.isOpened()) {
frame_count++;
// 捕获每一帧
cv::Mat Current_frame;
cap >> Current_frame;
if (Current_frame.empty()) {
break;
}
cv::Mat Current_frame_gray;
cv::cvtColor(Current_frame, Current_frame_gray, cv::COLOR_BGR2GRAY);
cv::GaussianBlur(Current_frame_gray, Current_frame_gray, cv::Size(21, 21), 0);
// 计算当前帧与前一帧的绝对差异
cv::Mat frame_diff;
cv::absdiff(Prev_frame_gray, Current_frame_gray, frame_diff);
// 阈值化差异图像
cv::Mat thresh;
cv::threshold(frame_diff, thresh, 25, 255, cv::THRESH_BINARY);
// 膨胀图像以填补空隙
cv::dilate(thresh, thresh, cv::Mat(), cv::Point(-1, -1), 4);
// 查找轮廓
std::vector<std::vector<cv::Point>> contours;
cv::findContours(thresh, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
for (const auto& cnt : contours) {
if (cv::contourArea(cnt) < 500) {
continue;
}
cv::Rect bounding_box = cv::boundingRect(cnt);
if (bounding_box.x <= 840 && bounding_box.y >= 150 && bounding_box.y <= 350) {
motion++;
cv::rectangle(Prev_frame, bounding_box, cv::Scalar(255, 255, 0), 3);
cv::putText(Prev_frame, "Motion detected", cv::Point(10, 20), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 2);
}
}
// 显示结果帧
cv::imshow("feed", Prev_frame);
// 更新前一帧
Prev_frame_gray = Current_frame_gray.clone();
if (cv::waitKey(1) == 'q') {
break;
}
}
cap.release();
cv::destroyAllWindows();
return 0;
}
6. 网络通讯问题,以及对SDK 结构的理解
根据幸狐的文档,修改优先级应该是没有问题的,但是没有说明原因。今天在执行rk_lunch.sh这个脚本的时候就发现问题了,这个脚本自己就有初始化网络的功能。所以把更新ip的脚本优先级挂的太高,提前进行年设置的ip地址会被rk_lunch替换。
方便自己找在这里也写一遍吧,
这也是幸狐官方没有点出来的问题,就是如何去建立自己的project。
RK的设计其实就是在/project/app里面新建自己的项目文件夹,里面有完整的初始化和启动配置。具体怎么新建自己的项目目前还没有具体研究,但是SDK快速开发指南里面有提及。因为整合项目对我来说优先级比较低,就先把程序跑起来,自己再写启动脚本达到开机自启的效果。
所以我的下一步做什么呢?目前的想法是做视频录制后对文件手动rtsp,进程和阻塞这种系统编程技术的学习,然后把opencv移植到rk_MPI平台吧。这些干累了看看webServer(nginx,Angular,fastcgi,appweb,Uhttp这样的)。
散会。
Views: 34
