【2022得捷电子创新设计大赛】我只是图像的搬运工
[复制链接]
本帖最后由 nemon 于 2022-10-30 15:27 编辑
这次做扫码显示功能。有个camera的例程,是从摄像头得到jpeg的图,然后转换成RGB565的数组,喂给lcd屏。
首先要解决在动态图上画框、写字的问题。
字模好办,用 KEIL带的 Font_6x8_h.h。写了个函数用于提取:
const unsigned int Font_cnt = 96;
const unsigned char Font_key[] = {
' ' ,'!' ,'"' ,'#' ,'$' ,'%' ,'&' ,'\'','(' ,')' ,'*' ,'+' ,
',' ,'-' ,'.' ,'/' ,'0' ,'1' ,'2' ,'3' ,'4' ,'5' ,'6' ,'7' ,
'8' ,'9' ,':' ,';' ,'<' ,'=' ,'>' ,'?' ,'@' ,'A' ,'B' ,'C' ,
'D' ,'E' ,'F' ,'G' ,'H' ,'I' ,'J' ,'K' ,'L' ,'M' ,'N' ,'O' ,
'P' ,'Q' ,'R' ,'S' ,'T' ,'U' ,'V' ,'W' ,'X' ,'Y' ,'Z' ,'[' ,
'\\',']' ,'^' ,'_' ,'\'','a' ,'b' ,'c' ,'d' ,'e' ,'f' ,'g' ,
'h' ,'i' ,'j' ,'k' ,'l' ,'m' ,'n' ,'o' ,'p' ,'q' ,'r' ,'s' ,
't' ,'u' ,'v' ,'w' ,'x' ,'y' ,'z' ,'{' ,'|' ,'}' ,'~' ,' ' ,
};
unsigned char * Font_BMP(char c){
unsigned int i=0;
unsigned char * p = (unsigned char *)Font_6x8_h ;
for(i=0;i<Font_cnt;i++){
if(c==Font_key){
p += i*8 ;
return p ;
}
}
return p;
}
画图遇到点小问题,例程里为了迁就lcd库,rgb565定义成了uint8_t数组。但是RGB565是16位啊,所以刚开始总是花屏乱码,后来强制(uint16_t*)rgb565就好了。
这样画图就变成了在数组里填色:
void draw_point(uint16_t* data, int y,int x,uint16_t color){
data[ y * IMAGE_WIDTH + x ] = color ;
return ;
}
void draw_rect(uint16_t* data, int y,int x,int h,int w,uint16_t color){
int i,j;
for(i=0;i<h;i++){
for(j=0;j<w;j++){
draw_point( data, y+i,x+j,color);
}
}
return ;
}
void draw_rect0(uint16_t* data, int y,int x,int h,int w,uint16_t color){
int i,j;
for(i=0;i<h;i++){
draw_point( data, y+i,x,color);
}
for(i=0;i<h;i++){
draw_point( data, y+i,x+w-1,color);
}
for(j=0;j<w;j++){
draw_point( data, y,x+j,color);
}
for(j=0;j<w;j++){
draw_point( data, y+h-1,x+j,color);
}
return ;
}
而写字就是按字模点点儿:
void set_char_6x8(uint16_t* data, int y,int x,unsigned char font[8] ,int color_black,uint16_t color_white ){
int i,j,h=8,w=6,v;
for(i=0;i<h;i++){
for(j=0;j<w;j++){
v= font & ( 1<<(w-j-1) ) ;
if(v>0){
data[ (y+i)*IMAGE_WIDTH + x+(w-j-1)] = color_black ;
}else{
data[ (y+i)*IMAGE_WIDTH + x+(w-j-1)] = color_white ;
}
}
}
return ;
}
void show_msg_6x8(uint16_t* data, int line ,int left,char * msg ){
int i=0,j=0,n=0,l=strlen(msg);
unsigned char * font;
while(line + i<IMAGE_HIGHT-8 && n <l){
while(left +j< IMAGE_WIDTH -6 && n<l){
font = Font_BMP( *(msg + n ) );
set_char_6x8( data, i+line , j+left ,font ,COLOR_BLACK, COLOR_WHITE );
//printf( "[%d,%d]\n", i+line , j+left );
n++;
j+=6;
}
i+=8;
j=0;
}
return ;
}
这个项目,没有用二维码,闭门造车德搞了一个彩色码(就是图省事)。
识别起来算法也容易——在屏幕上画4个框,当每个框里颜色的平均值符合阈值时,就认为是该颜色,那么4个框就的组合就可以确定一个简短的代码了。
取景待扫描状态是这样的:
然后把刚才那张纸在镜头前一晃(别太快),还是用数组取数,分别求rgb三色的平均值:
int get_avg(uint16_t* data, int y,int x,int h,int w,int left ,int length ){
int i,j,v,mask=(1<<length)-1;
long long sum=0;
for(i=0;i<h;i++){
for(j=0;j<w;j++){
v=( uint16_exchange_HL(data[ (y+i)*IMAGE_WIDTH + (x+j) ]) >> left ) & mask ;
sum+=v;
}
}
//printf("%lld -> %lld . %d \n", sum ,sum/(w*h) ,mask );
return sum/(w*h);
}
int ger_color_idx( uint8_t r , uint8_t g , uint8_t b ){
if(r>COLOR_THRESHOLD_HIGH_RED && g <=COLOR_THRESHOLD_LOW_GREEN && b<=COLOR_THRESHOLD_LOW_BLUE){
return COLOR_CAM_RED;
}
if(r<=COLOR_THRESHOLD_LOW_RED && g >COLOR_THRESHOLD_HIGH_GREEN && b<=COLOR_THRESHOLD_LOW_BLUE){
return COLOR_CAM_GREEN;
}
if(r<=COLOR_THRESHOLD_LOW_RED && g <=COLOR_THRESHOLD_LOW_GREEN && b>COLOR_THRESHOLD_HIGH_BLUE){
return COLOR_CAM_BLUE;
}
if(r>COLOR_THRESHOLD_HIGH_RED && g >COLOR_THRESHOLD_HIGH_GREEN && b>COLOR_THRESHOLD_HIGH_BLUE){
return COLOR_CAM_WHITE;
}
return COLOR_CAM_UNKONW;
}
int check_color_idx( int r0, int g0, int b0, int r1, int g1, int b1, int r2, int g2, int b2, int r3, int g3, int b3 ){
if(
COLOR_CAM_WHITE == ger_color_idx( r0,g0,b0 )
&& COLOR_CAM_GREEN == ger_color_idx( r1,g1,b1 )
&& COLOR_CAM_RED == ger_color_idx( r2,g2,b2 )
&& COLOR_CAM_BLUE == ger_color_idx( r3,g3,b3 )
){
return 2;
}
return -1;
}
这样就可以识别了,结果是这样:
显示内容很简单:" You find it ! This is a leaf ."
遗憾的是,增加网络功能后,出现了摄像头申请DMA内存不够了,还未解决。
I (5874) cam_hal: buffer_size: 16384, half_buffer_size: 1024, node_buffer_size: 1024, node_cnt: 16, total_cnt: 15
I (5874) cam_hal: Allocating 15360 Byte frame buffer in PSRAM ...
E (5884) cam_hal: cam_dma_config(310): frame buffer malloc failed
E (5884) cam_hal: cam_config(394): cam_dma_config failed
E (5894) camera: Camera config failed with error 0xffffffff
E (5904) decode-TAG: Camera Init Failed
视频演示了操作过程,我给这个码配的展品有点小……
VID_20221030_115503 扫描彩色码
福利——源码:识别彩色码
|