Image scaling example with DISCO_F746NG board and STM32F4DIS-CAM Camera module.
Dependencies: mbed LCD_DISCO_F746NG BSP_DISCO_F746NG
camera_app.cpp
- Committer:
- kashgarim
- Date:
- 2020-02-01
- Revision:
- 0:ce3028d3b22a
File content as of revision 0:ce3028d3b22a:
#include "mbed.h" #include "stm32746g_discovery_camera.h" #include "LCD_DISCO_F746NG.h" #include "stm32f7xx_hal_dcmi.h" extern "C" { //defined in stm32746g_discovery_camera.c extern DCMI_HandleTypeDef hDcmiHandler; //void DCMI_IRQHandler(void) { // HAL_DCMI_IRQHandler(&hDcmiHandler); //} //void DMA2_Stream1_IRQHandler(void) { // HAL_DMA_IRQHandler(hDcmiHandler.DMA_Handle); //} } // 2 input channels, as input is in RGB565 format #define NUM_IN_CH 2 #define NUM_OUT_CH 3 #define IMG_WIDTH 160 #define IMG_HEIGHT 120 #define CNN_IMG_SIZE 32 #define resolution RESOLUTION_R160x120 uint8_t camera_buffer[NUM_IN_CH*IMG_WIDTH*IMG_HEIGHT]; uint8_t resized_buffer[NUM_OUT_CH*CNN_IMG_SIZE*CNN_IMG_SIZE]; char lcd_output_string[50]; LCD_DISCO_F746NG lcd; Serial pc(USBTX, USBRX); void resize_rgb565in_rgb888out(uint8_t* camera_image, uint8_t* resize_image) { // offset so that only the center part of rectangular image is selected for resizing int width_offset = ((IMG_WIDTH-IMG_HEIGHT)/2)*NUM_IN_CH; int yresize_ratio = (IMG_HEIGHT/CNN_IMG_SIZE)*NUM_IN_CH; int xresize_ratio = (IMG_WIDTH/CNN_IMG_SIZE)*NUM_IN_CH; int resize_ratio = (xresize_ratio<yresize_ratio)?xresize_ratio:yresize_ratio; for(int y=0; y<CNN_IMG_SIZE; y++) { for(int x=0; x<CNN_IMG_SIZE; x++) { int orig_img_loc = (y*IMG_WIDTH*resize_ratio + x*resize_ratio + width_offset); // correcting the image inversion here int out_img_loc = ((CNN_IMG_SIZE-1-y)*CNN_IMG_SIZE + (CNN_IMG_SIZE-1-x))*NUM_OUT_CH; uint8_t pix_lo = camera_image[orig_img_loc]; uint8_t pix_hi = camera_image[orig_img_loc+1]; // convert RGB565 to RGB888 resize_image[out_img_loc] = (0xF8 & pix_hi); resize_image[out_img_loc+1] = ((0x07 & pix_hi)<<5) | ((0xE0 & pix_lo)>>3); resize_image[out_img_loc+2] = (0x1F & pix_lo) << 3; } } } void display_image_rgb888(int x_dim, int y_dim, uint8_t* image_data) { for(int y=0; y<y_dim; y++) { for(int x=0; x<x_dim; x++) { int pix_loc = (y*x_dim + x)*3; uint8_t a = 0xFF; uint8_t r = image_data[pix_loc]; uint8_t g = image_data[pix_loc+1]; uint8_t b = image_data[pix_loc+2]; int pixel = a<<24 | r<<16 | g<<8 | b; lcd.DrawPixel(300+x, 100+y, pixel); } } } void display_image_rgb565(int x_dim, int y_dim, uint8_t* image_data) { for(int y=0; y<y_dim; y++) { for(int x=0; x<x_dim; x++) { int pix_loc = (y*x_dim + x)*2; uint8_t a = 0xFF; uint8_t pix_lo = image_data[pix_loc]; uint8_t pix_hi = image_data[pix_loc+1]; uint8_t r = (0xF8 & pix_hi); uint8_t g = ((0x07 & pix_hi)<<5) | ((0xE0 & pix_lo)>>3); uint8_t b = (0x1F & pix_lo) << 3; int pixel = a<<24 | r<<16 | g<<8 | b; // inverted image, so draw from bottom-right to top-left lcd.DrawPixel(200-x, 160-y, pixel); } } } int main() { int count=0; HAL_Init(); wait_ms(100); pc.baud(115200); lcd.Clear(LCD_COLOR_WHITE); //lcd.Clear(0xFF0F9D58); //lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"I heard yes! I love yes. :)", CENTER_MODE); if( BSP_CAMERA_Init(resolution) == CAMERA_OK ) { pc.printf("Camera init - SUCCESS\r\n"); } else { pc.printf("Camera init - FAILED\r\n"); lcd.Clear(LCD_COLOR_RED); } while(1) { BSP_CAMERA_SnapshotStart(camera_buffer); resize_rgb565in_rgb888out(camera_buffer, resized_buffer); display_image_rgb888(CNN_IMG_SIZE, CNN_IMG_SIZE, resized_buffer); display_image_rgb565(IMG_WIDTH, IMG_HEIGHT, camera_buffer); // run neural network sprintf(lcd_output_string,"Original vs. scaled images"); lcd.DisplayStringAt(0, LINE(8), (uint8_t *)lcd_output_string, CENTER_MODE); /*sprintf(lcd_output_string,"Counter index:%d",count++); lcd.Clear(0xFF0F9D58); lcd.DisplayStringAt(0, LINE(8), (uint8_t *)lcd_output_string, CENTER_MODE); pc.printf("%s\r\n",lcd_output_string); wait_ms(1000);*/ } }