1 #include <CRecognition.h>
3 #define min(a,b) ((a) < (b) ? (a) : (b))
4 #define max(a,b) ((a) > (b) ? (a) : (b))
6 //Vymazani promennych a jejich nastaveni na pocatecni hodnoty
7 CRecognition::CRecognition()
9 memset(learned,0,sizeof(unsigned char)*3);
10 memset(colorArray,0,64*64*64);
18 CRecognition::~CRecognition()
22 //zvysi prah t, toleranci podobnosti vzorovemu pixelu
23 void CRecognition::increaseTolerance()
26 if (tolerance > 400) tolerance = 400;
27 fprintf(stdout,"Tolerance: %i\n",tolerance);
30 //snizi prah t, toleranci podobnosti vzorovemu pixelu
31 void CRecognition::decreaseTolerance()
34 if (tolerance < 0) tolerance = 0;
35 fprintf(stdout,"Tolerance: %i\n",tolerance);
38 //smaze indexovaci tabulku
39 void CRecognition::resetColorMap()
41 memset(colorArray,0,64*64*64);
45 void CRecognition::learnPixel(unsigned char* a,unsigned char color [3])
48 //ulozi pixel do vzoroveho
49 for (int i =0;i<3;i++) learned[i] = a[i];
51 for (int i =0;i<3;i++) learned[i] = color[i];
53 //prevede nauceny pixel do HSV
54 rgbToHsv(learned[0],learned[1],learned[2],&learnedHue,&learnedSaturation,&learnedValue);
56 //z daneho vzoru vytvori indexovaci tabulku
58 for (int r=0;r<256;r+=4){
60 for (int g=0;g<256;g+=4){
62 for (int b=0;b<256;b+=4){
64 int i = ((r/4)*64+g/4)*64+b/4;
65 colorArray[i] = evaluatePixel3(u);
69 fprintf(stdout,"Learned RGB: %i %i %i, HSV: %i %i %i\n",learned[0],learned[1],learned[2],learnedHue,learnedSaturation,learnedValue);
72 //vrati podobnost pixelu metodou indexovaci tabulky - metoda z dilu IV
73 int CRecognition::evaluatePixelFast(unsigned char *a)
75 int b = ((a[0]/4)*64+a[1]/4)*64+a[2]/4;
79 //podobnost pixelu - prvni metoda z dilu III
80 float CRecognition::evaluatePixel1(unsigned char* a)
83 for (int i =0;i<3;i++){
84 result += pow((int)a[i]-(int)learned[i],2);
89 //podobnost pixelu - druha metoda z dilu III
90 float CRecognition::evaluatePixel2(unsigned char* a)
93 for (int i =0;i<3;i++){
94 result += pow((int)a[i]-(int)learned[i],2);
96 result = sqrt(result);
97 if (result > tolerance) result = 0; else result = 1;
101 //podobnost pixelu - druha metoda z dilu III
102 float CRecognition::evaluatePixel3(unsigned char* a)
107 rgbToHsv(a[0],a[1],a[2],&h,&s,&v);
108 if (v > 40 && s > 40){
109 result = result + pow((int)h-(int)learnedHue,2);
110 result = result + pow((int)s-(int)learnedSaturation,2)/4;
111 result = result + pow((int)v-(int)learnedValue,2)/16;
115 result = sqrt(result);
116 if (result > tolerance) result = 0; else result = 1;
120 //segmentace obrazu - metoda z dilu IV
121 SPixelPosition CRecognition::findSegment(CRawImage* image)
123 SPixelPosition result;
128 int expand[4] = {image->width,-image->width,1,-1};
129 int stack[image->width*image->height];
130 int stackPosition = 0;
133 int buffer[image->width*image->height];
134 int len = image->width*image->height;
136 //oznacime oblasti s hledanou barvou
137 for (int i = 0;i<len;i++) buffer[i] = -evaluatePixelFast(&image->data[3*i]);
139 //'ukrojime' okraje obrazu
140 int pos = (image->height-1)*image->width;
141 for (int i = 0;i<image->width;i++){
145 for (int i = 0;i<image->height;i++){
146 buffer[image->width*i] = 0;
147 buffer[image->width*i+image->width-1] = 0;
150 //zacneme prohledavani
152 for (int i = 0;i<len;i++){
153 //pokud je nalezen pixel s hledanou barvou,
154 if (buffer[i] < 0 && numSegments < MAX_SEGMENTS){
156 //zalozime dalsi segment
157 buffer[i] = ++numSegments;
158 segmentArray[numSegments-1].size = 1;
159 segmentArray[numSegments-1].x = i%image->width;
160 segmentArray[numSegments-1].y = i/image->width;
161 //a umistime souradnice pixelu na vrchol zasobniku
162 stack[stackPosition++] = i;
163 //dokud neni zasobnik prazdny
164 while (stackPosition > 0){
165 //vyjmeme ze zasobniku pozici posledne vlozeneho pixelu
166 position = stack[--stackPosition];
167 //prohledame pixely na sousednich pozicich
168 for (int j =0;j<4;j++){
169 pos = position+expand[j];
170 //a pokud maji hledanou barvu,
171 if (buffer[pos] < 0){
172 //vlozime je do zasobniku,
173 stack[stackPosition++] = pos;
174 //pridame jejich pozici do souradnic aktualniho segmentu
175 segmentArray[numSegments-1].x += pos%image->width;
176 segmentArray[numSegments-1].y += pos/image->width;
177 //a zvetsime velikost segmentu
178 segmentArray[numSegments-1].size++;
179 buffer[pos] = numSegments;
183 //jakmile se zasobnik vyprazdni, tj. byly nalezeny vsechny pisely daneho segmentu spocteme teziste segmentu
184 segmentArray[numSegments-1].x = segmentArray[numSegments-1].x/segmentArray[numSegments-1].size;
185 segmentArray[numSegments-1].y = segmentArray[numSegments-1].y/segmentArray[numSegments-1].size;
189 //Najde nejvetsi segment
193 for (i =0;i<numSegments;i++){
194 if (maxSize < segmentArray[i].size){
196 maxSize = segmentArray[i].size;
199 if (debug) fprintf(stdout,"Largest segment is %i %i %i %i\n",index,segmentArray[index].size,segmentArray[index].x,segmentArray[index].y);
201 //a spocte jeho stred
203 result.x = segmentArray[index].x;
204 result.y = segmentArray[index].y;
206 //fprintf(stdout,"xy = %i %i\n", result.x, result.y);
209 //vykreslime vysledek
211 for (int i = 0;i<len;i++){
214 image->data[i*3+j%3] = 0;
215 image->data[i*3+(j+1)%3] = 255;
216 image->data[i*3+(j+2)%3] = 255;
224 //nalezeni teziste pixelu dane tridy - metoda z dilu III
225 SPixelPosition CRecognition::findMean(CRawImage* image)
227 //priprava promennych pro vypocet
228 SPixelPosition result;
229 float sumX,sumY,eval,sumEval;
230 sumX=sumY=eval=sumEval=0;
232 int yconst = image->width;
235 for (int y = 0;y<image->height;y+=step){
236 yconst = image->width*y;
237 for (int x = 0;x<image->width;x+=step){
238 //vyhodnoceni podobnosti pixelu
239 eval=evaluatePixelFast(&image->data[3*(x+yconst)]);
240 //vybarveni vysledku v obraze
242 for (int i = 0;i<3;i++) image->data[3*(x+yconst)+i]=255-learned[i];
245 sumX = sumX + x*eval;
246 sumY = sumY + y*eval;
249 //pokud byl nalezen alespon jeden pixel, je proveden vypocet teziste
254 sumX = image->width/2;
255 sumY = image->height/2;
258 result.x = (int)(sumX);
259 result.y = (int)(sumY);
260 //fprintf(stdout,"x2y2 = %i %i\n", result.x, result.y);
264 //prevod RGB -> HSV, prevzato z www
265 void CRecognition::rgbToHsv(unsigned char r, unsigned char g, unsigned char b, unsigned int *hue, unsigned char *saturation, unsigned char *value )
267 float min, max, delta;
271 *saturation = (unsigned char) s;
272 *value = (unsigned char) v;
273 *hue = (unsigned int) h;
275 min = min( r, min(g, b) );
276 max = max( r, max(g, b) );
282 s = min(delta*255 / max,255);
290 h = ( g - b ) / delta; // between yellow & magenta
292 h = 2 + ( b - r ) / delta; // between cyan & yellow
294 h = 4 + ( r - g ) / delta; // between magenta & cyan
297 *saturation = (unsigned char) s;
298 *value = (unsigned char) v;
299 *hue = (unsigned int) h;