-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSpresense_Camera_Histogram.ino
152 lines (134 loc) · 4.78 KB
/
Spresense_Camera_Histogram.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <Camera.h>
#include <Adafruit_ILI9341.h>
//ディスプレイの設定
#define TFT_DC 9
#define TFT_CS 10
Adafruit_ILI9341 display = Adafruit_ILI9341(TFT_CS, TFT_DC);
#define DISPLAY_WIDTH 320
#define DISPLAY_HEIGHT 240
//画像の一辺の長さ
#define IMG_EDGE_LEN 128
//撮影データを入れる配列
uint8_t R[IMG_EDGE_LEN][IMG_EDGE_LEN];
uint8_t G[IMG_EDGE_LEN][IMG_EDGE_LEN];
uint8_t B[IMG_EDGE_LEN][IMG_EDGE_LEN];
//ヒストグラム描画時の高さ上限
#define HIST_MAX_HEIGHT (DISPLAY_HEIGHT / 3)
//ヒストグラムの棒がいくつあるか
#define HIST_NUM (HIST_MAX_HEIGHT)
//ヒストグラムデータ格納用
int histR[HIST_NUM];
int histG[HIST_NUM];
int histB[HIST_NUM];
int histMaxCommon = 0;
bool camInit(){
CamErr err;
err = theCamera.begin(1,CAM_VIDEO_FPS_30,IMG_EDGE_LEN,IMG_EDGE_LEN,CAM_IMAGE_PIX_FMT_YUV422,7);
if (err != CAM_ERR_SUCCESS)
{
return false;
}
Serial.println("Set Auto white balance parameter");
err = theCamera.setAutoWhiteBalanceMode(CAM_WHITE_BALANCE_DAYLIGHT);
if (err != CAM_ERR_SUCCESS)
{
return false;
}
Serial.println("Set still picture format");
err = theCamera.setStillPictureImageFormat(1024,1024,CAM_IMAGE_PIX_FMT_JPG);
if (err != CAM_ERR_SUCCESS)
{
return false;
}
return true;
}
// RGB565を出力
bool camCapRGB128(uint8_t R[IMG_EDGE_LEN][IMG_EDGE_LEN], uint8_t G[IMG_EDGE_LEN][IMG_EDGE_LEN], uint8_t B[IMG_EDGE_LEN][IMG_EDGE_LEN], CamImage img){
CamErr err = img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565);
uint16_t* imgbuf = (uint16_t*)img.getImgBuff();
for (int n = 0; n < IMG_EDGE_LEN*IMG_EDGE_LEN; ++n) {
R[(int)(n/IMG_EDGE_LEN)][n%IMG_EDGE_LEN] = (uint8_t)((imgbuf[n] & 0xf800) >> 11);
G[(int)(n/IMG_EDGE_LEN)][n%IMG_EDGE_LEN] = (uint8_t)((imgbuf[n] & 0x07e0) >> 5 );
B[(int)(n/IMG_EDGE_LEN)][n%IMG_EDGE_LEN] = (uint8_t)(imgbuf[n] & 0x001f);
}
return true;
}
void SetTextOnDisplay(String str, int startX, int startY, int color){
int len = str.length();
//display.fillRect(0,224, 320, 240, ILI9341_BLACK);
display.setTextSize(2);
display.setCursor(startX, startY);
display.setTextColor(color);
display.println(str);
}
void calcHistogram(uint8_t data[IMG_EDGE_LEN][IMG_EDGE_LEN], int hist[HIST_NUM], int max_pixel_value){
//ヒストグラム初期化
for(int i=0; i<HIST_NUM; i++){
hist[i] = 0;
}
//ヒストグラム作成
for(int i=0; i<IMG_EDGE_LEN; i++){
for(int j=0; j<IMG_EDGE_LEN; j++){
//data[i][j]を0-max_pixel_valueの範囲から0-HIST_NUMの範囲にマッピング
int index = (int)((float)data[i][j] / (float)max_pixel_value * (float)HIST_NUM) - 1;
hist[index] += 1;
}
}
//ヒストグラムの最大値取得
int histMax = 0;
for(int i=0; i<HIST_NUM; i++){
if(hist[i] > histMax) histMax = hist[i];
}
//グローバル変数のヒストグラム最大値を更新
if(histMax > histMaxCommon) histMaxCommon = histMax;
}
void drawHistogram(int hist[HIST_NUM], int startX, int startY, int color){
//ヒストグラムの描画
display.fillRect(startX, startY, HIST_NUM, HIST_MAX_HEIGHT, ILI9341_BLACK);
int normHist = 0;
for(int i=0; i<HIST_NUM; i++){
//histMaxCommonが最大となるよう正規化
if(histMaxCommon != 0){
normHist = (int)((float)hist[i] * (float)HIST_MAX_HEIGHT / (float)histMaxCommon);
}
display.drawLine(startX+i, startY+HIST_MAX_HEIGHT, startX+i, startY+HIST_MAX_HEIGHT-normHist, color);
}
}
void CamCB(CamImage img) {
camCapRGB128(R,G,B,img);
Serial.println();
Serial.println();
img.convertPixFormat(CAM_IMAGE_PIX_FMT_RGB565);
display.drawRGBBitmap(0, 0, (uint16_t *)img.getImgBuff(), IMG_EDGE_LEN, IMG_EDGE_LEN);
//ヒストグラム描画開始位置
int startX = IMG_EDGE_LEN + 5;
int startY = 0;
int textOffset = 5;
histMaxCommon = 0;
calcHistogram(R, histR, 31);
calcHistogram(G, histG, 63);
calcHistogram(B, histB, 31);
SetTextOnDisplay("R", startX+HIST_NUM+textOffset, startY, ILI9341_RED);
drawHistogram(histR, startX, startY, ILI9341_RED);
SetTextOnDisplay("G", startX+HIST_NUM+textOffset, startY+HIST_MAX_HEIGHT, ILI9341_GREEN);
drawHistogram(histG, startX, startY+HIST_MAX_HEIGHT, ILI9341_GREEN);
SetTextOnDisplay("B", startX+HIST_NUM+textOffset, startY+2*HIST_MAX_HEIGHT, ILI9341_BLUE);
drawHistogram(histB, startX, startY+HIST_MAX_HEIGHT*2, ILI9341_BLUE);
}
void setup() {
//シリアル通信開始
Serial.begin(115200);
//ディスプレイ初期化
display.begin();
display.setRotation(3);
display.fillScreen(ILI9341_BLACK);
//カメラ初期化
if(!camInit()){
Serial.println("Failed to initialize camera");
}
//カメラストリーミング開始
if (theCamera.startStreaming(true, CamCB) != CAM_ERR_SUCCESS){
Serial.println("Failed to stream camera");
}
}
void loop() { }