经过不懈努力,实现了单通道的的运动检测,参数不是很理想,导致结果很极端。

不过从性能来看,这次我们充分使用了npu加速,cpu占用很低而且温度也很低,适合长期跑着,验证了运动检测的可行性。

直接贴代码吧

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <time.h>
#include <unistd.h>
#include <vector>
#include "sample_comm.h"

typedef struct _rkMpiCtx
{
	SAMPLE_VI_CTX_S vi;
} SAMPLE_MPI_CTX_S;

RK_U64 TEST_COMM_GetNowUs()
{
	struct timespec time = {0, 0};
	clock_gettime(CLOCK_MONOTONIC, &time);
	return (RK_U64)time.tv_sec * 1000000 + (RK_U64)time.tv_nsec / 1000; /* microseconds */
}

static MPP_CHN_S vi_chn, ivs_chn;
int md_area_threshold = 640 * 360 * 0.3;

int main(int argc, char *argv[])
{
	system("RkLunch-stop.sh");
	// config vi
	RK_S32 s32Ret = RK_SUCCESS;
	SAMPLE_MPI_CTX_S *ctx;
	RK_U32 u32ViWidth = 640;
	RK_U32 u32ViHeight = 360;
	RK_CHAR *pOutPath = NULL;
	RK_CHAR *pDeviceName = NULL;
	RK_S32 s32CamId = 0;
	RK_S32 s32ChnId = 1;
	RK_S32 s32loopCnt = -1;
	PIXEL_FORMAT_E PixelFormat = RK_FMT_RGB565;
	COMPRESS_MODE_E CompressMode = COMPRESS_MODE_NONE;
	rk_aiq_working_mode_t hdr_mode = RK_AIQ_WORKING_MODE_NORMAL;
	ctx = (SAMPLE_MPI_CTX_S *)(malloc(sizeof(SAMPLE_MPI_CTX_S)));
	memset(ctx, 0, sizeof(SAMPLE_MPI_CTX_S));

	// init rkaiq
	RK_BOOL multi_sensor = RK_FALSE;
	const char *iq_dir = "/etc/iqfiles";
	// hdr_mode = RK_AIQ_WORKING_MODE_ISP_HDR2;
	SAMPLE_COMM_ISP_Init(0, hdr_mode, multi_sensor, iq_dir);
	SAMPLE_COMM_ISP_Run(0);

	// init mpi
	RK_MPI_SYS_Init();

	// Init VI
	{
		ctx->vi.u32Width = u32ViWidth;
		ctx->vi.u32Height = u32ViHeight;
		ctx->vi.s32DevId = s32CamId;
		ctx->vi.u32PipeId = ctx->vi.s32DevId;
		ctx->vi.s32ChnId = s32ChnId;
		ctx->vi.stChnAttr.stIspOpt.u32BufCount = 2;
		ctx->vi.stChnAttr.stIspOpt.enMemoryType = VI_V4L2_MEMORY_TYPE_DMABUF;
		ctx->vi.stChnAttr.u32Depth = 1;
		ctx->vi.stChnAttr.enPixelFormat = PixelFormat;
		ctx->vi.stChnAttr.enCompressMode = CompressMode;
		ctx->vi.stChnAttr.stFrameRate.s32SrcFrameRate = -1;
		ctx->vi.stChnAttr.stFrameRate.s32DstFrameRate = -1;
		ctx->vi.dstFilePath = pOutPath;
		ctx->vi.s32loopCount = s32loopCnt;
	}

	SAMPLE_COMM_VI_CreateChn(&ctx->vi);
	RK_MPI_VI_EnableChn(0, 1);

	// init ivs
	IVS_CHN_ATTR_S attr;

	memset(&attr, 0, sizeof(attr));
	// config ivs
	{
		attr.enMode = IVS_MODE_MD_OD;
		attr.u32PicWidth = 640;
		attr.u32PicHeight = 360;
		attr.enPixelFormat = RK_FMT_YUV420SP;
		attr.s32Gop = 60;
		attr.bSmearEnable = RK_FALSE;
		attr.bWeightpEnable = RK_FALSE;
		attr.bMDEnable = RK_TRUE;
		attr.s32MDInterval = 5;
		attr.bMDNightMode = RK_FALSE;
		attr.u32MDSensibility = 1;
		attr.bODEnable = RK_TRUE;
		attr.s32ODInterval = 1;
		attr.s32ODPercent = 7;
	}
	RK_MPI_IVS_CreateChn(0, &attr);
	IVS_MD_ATTR_S stMdAttr;
	memset(&stMdAttr, 0, sizeof(stMdAttr));
	s32Ret = RK_MPI_IVS_GetMdAttr(0, &stMdAttr);
	if (s32Ret)
	{
		RK_LOGE("ivs get mdattr failed:%x", s32Ret);
		while (1)
		{
			printf("ivs get mdattr failed:%x", s32Ret);
		}
	}
	stMdAttr.s32ThreshSad = 400;
	stMdAttr.s32ThreshMove = 2;
	stMdAttr.s32SwitchSad = 0;
	// update configuration
	s32Ret = RK_MPI_IVS_SetMdAttr(0, &stMdAttr);
	if (s32Ret)
	{
		while (1)
		{
			printf("ivs set mdattr failed:%x", s32Ret);
		}
	}
	// bind vi and ivs
	vi_chn.enModId = RK_ID_VI;
	vi_chn.s32DevId = 0;
	vi_chn.s32ChnId = 1;
	ivs_chn.enModId = RK_ID_IVS;
	ivs_chn.s32DevId = 0;
	ivs_chn.s32ChnId = 0;
	s32Ret = RK_MPI_SYS_Bind(&vi_chn, &ivs_chn);
	if (s32Ret)
	{
		while (1)
		{
			printf("ivs set mdattr failed:%x", s32Ret);
		}
	}
	IVS_RESULT_INFO_S stResults;
	memset(&stResults, 0, sizeof(IVS_RESULT_INFO_S));
	while (1)
	{
		s32Ret = RK_MPI_IVS_GetResults(0, &stResults, -1);
		if (s32Ret == RK_SUCCESS)
		{
			if (stResults.s32ResultNum == 1)
			{
				printf("MD u32RectNum: %u\n", stResults.pstResults->stMdInfo.u32RectNum);
				//for (int i = 0; i < stResults.pstResults->stMdInfo.u32RectNum; i++)
				{
					if (stResults.pstResults->stMdInfo.u32Square > md_area_threshold)
					{
						printf("MD: md_area is %d, md_area_threshold is %d\n",
					         stResults.pstResults->stMdInfo.u32Square, md_area_threshold);
						/*printf("%d: [%d, %d, %d, %d]\n", i,
							   stResults.pstResults->stMdInfo.stRect[i].s32X,
							   stResults.pstResults->stMdInfo.stRect[i].s32Y,
							   stResults.pstResults->stMdInfo.stRect[i].u32Width,
							   stResults.pstResults->stMdInfo.stRect[i].u32Height);*/
					}
				}
			}
			RK_MPI_IVS_ReleaseResults(0, &stResults);
		}
		else
		{
			RK_LOGE("RK_MPI_IVS_GetResults fail %x", s32Ret);
		}
	}


	// Destory Pool
	RK_MPI_VI_DisableChn(0, 0);
	RK_MPI_VI_DisableDev(0);
	RK_MPI_IVS_DestroyChn(0);

	SAMPLE_COMM_ISP_Stop(0);

	RK_MPI_SYS_Exit();

	return 0;
}

思路大概是这样,通道标签MPP_CHN_S和上下文_rkMpiCtx先准备好,启动isp(rkaiq),启动mpi,配置vi,创建vi通道,配置和创建ivs,配置运动检测的结构体,使用RK_MPI_IVS_SetMdAttr生效,再更新通道标签,对相应的通道进行绑定,最后一直获取结果,释放结果就ok。

cmake_minimum_required(VERSION 3.10)
# Configure the compiler
set(SDK_PATH $ENV{LUCKFOX_SDK_PATH})
if(NOT SDK_PATH)
    message(FATAL_ERROR "Please Set Luckfox-pico SDK Path. Such as:export LUCKFOX_SDK_PATH=/home/user/luckfox-pico")
    return()
endif()
set(CMAKE_C_COMPILER "${SDK_PATH}/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc"
)
set(CMAKE_CXX_COMPILER "${SDK_PATH}/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-g++"
)

# Project Name
project("MyMD")

# Set the library directory
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib)

set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")
add_definitions(-DRV1106_1103)

#Thread
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)

file(GLOB SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc")
add_executable(${PROJECT_NAME} ${SRC_FILES})

add_compile_options(-g -Wall
                    -DISP_HW_V30 -DRKPLATFORM=ON -DARCH64=OFF
                    -DROCKIVA -DUAPI2
                    -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 
                    )

set(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath-link,${CMAKE_CURRENT_SOURCE_DIR}/lib:/usr/lib")

target_link_libraries(${PROJECT_NAME}  
                    ${LIBRKNNRT}
                    Threads::Threads
                    rockiva
                    sample_comm
                    rockit
                    rockchip_mpp
                    rkaiq
                    pthread
                    rtsp
                    )

target_include_directories(${PROJECT_NAME} PRIVATE                        
                            ${OpenCV_INCLUDE_DIRS}
                            ${CMAKE_CURRENT_SOURCE_DIR}
                            ${CMAKE_CURRENT_SOURCE_DIR}/utils
                            ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/rknpu2/include
                            ${CMAKE_CURRENT_SOURCE_DIR}/common 
                            ${CMAKE_CURRENT_SOURCE_DIR}/common/isp3.x   
                            ${CMAKE_CURRENT_SOURCE_DIR}/include
                            ${CMAKE_CURRENT_SOURCE_DIR}/include/rknn
                            ${CMAKE_CURRENT_SOURCE_DIR}/include/rkaiq
                            ${CMAKE_CURRENT_SOURCE_DIR}/include/rkaiq/uAPI2
                            ${CMAKE_CURRENT_SOURCE_DIR}/include/rkaiq/common
                            ${CMAKE_CURRENT_SOURCE_DIR}/include/rkaiq/xcore
                            ${CMAKE_CURRENT_SOURCE_DIR}/include/rkaiq/algos
                            ${CMAKE_CURRENT_SOURCE_DIR}/include/rkaiq/iq_parser
                            ${CMAKE_CURRENT_SOURCE_DIR}/include/rkaiq/iq_parser_v2
                            ${CMAKE_CURRENT_SOURCE_DIR}/include/rkaiq/smartIr
                          )
                          

set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/install/${PROJECT_NAME}_demo")
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX})                

Views: 44

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.