1296 views|0 replies

183

Posts

12

Resources
The OP
 

[2022 Digi-Key Innovation Design Competition] I am just an image porter [Copy link]

 This post was last edited by nemon on 2022-10-30 15:27

This time we are going to do the scan code display function. There is a camera routine that gets the jpeg image from the camera, then converts it into an RGB565 array and feeds it to the LCD screen.

The first thing to solve is the problem of drawing frames and writing on dynamic pictures.

The font is easy to handle. Use Font_6x8_h.h from KEIL. Write a function to extract it:

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;
}

I encountered a little problem in drawing. In the example, in order to accommodate the LCD library, rgb565 was defined as a uint8_t array. But RGB565 is 16 bits, so at first the screen was always garbled, and later it was forced to (uint16_t*) rgb565.

This way drawing becomes filling in the array:


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 ;
}

And writing is just following the letter pattern:


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 ;
}

This project did not use a QR code. Instead, we developed a color code behind closed doors (just to save trouble).

The recognition algorithm is also easy - draw 4 boxes on the screen, and when the average value of the color in each box meets the threshold, it is considered to be that color, so the combination of the 4 boxes can determine a short code.

The state of the viewfinder to be scanned is as follows:

Then wave the piece of paper in front of the camera (not too fast), and use the array to get the average value of the three RGB colors:

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;
}

This way it can be identified, the result is like this:

The display content is simple: "You found it! This is a leaf."

Unfortunately, after adding the network function, the problem of insufficient DMA memory requested by the camera has not been resolved yet.

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

The video demonstrates the operation process. The exhibit I matched with this code is a bit small...

VID_20221030_115503 扫描彩色码

Benefits——Source code: Recognize color codes

This post is from DigiKey Technology Zone
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list