source: foam/trunk/vision/src/Image.cpp @ 96

Revision 96, 8.3 KB checked in by dave, 10 years ago (diff)

Benchmark testing added for the eigen face recognition

Line 
1// Copyright (C) 2009 foam
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License as published by
5// the Free Software Foundation; either version 2 of the License, or
6// (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License
14// along with this program; if not, write to the Free Software
15// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
17#include "Image.h"
18
19#include <iostream>
20#include "highgui.h"
21
22using namespace std;
23
24Image::Image(int w, int h, int d, int c)
25{
26        m_Image=cvCreateImage(cvSize(w, h), d, c);
27}
28
29Image::Image(const string &filename)
30{
31        m_Image=cvLoadImage(filename.c_str());
32        if (m_Image==NULL) cerr<<"Could not open image: "<<filename<<endl;
33        assert(m_Image);
34}
35
36Image::Image(const Image &other)
37{
38        m_Image=cvCloneImage(other.m_Image);
39}
40
41Image::Image(const IplImage *other)
42{
43        m_Image=cvCloneImage(other);
44}
45
46Image::Image(int w, int h, int c, const Vector<float> &v, float gain)
47{
48        m_Image=cvCreateImage(cvSize(w, h), 8, c);
49        unsigned int pos=0;
50        for(int y=0; y<m_Image->height; y++)
51        {
52        for(int x=0; x<m_Image->width; x++)
53                {
54                        CvScalar s;
55                        for (int c=0; c<m_Image->nChannels; c++)
56                        {
57                                s.val[c]=(0.5+v[pos++]*gain)*127.0f;
58                        }
59                        cvSet2D(m_Image,y,x,s);
60                }
61        }
62}
63
64Image::~Image()
65{
66        cvReleaseImage(&m_Image);
67}
68
69void Image::Clear()
70{
71    for(int y=0; y<m_Image->height; y++)
72        {
73        for(int x=0; x<m_Image->width; x++)
74                {
75                        CvScalar v;
76                       
77                        for (int c=0; c<m_Image->nChannels; c++)
78                        {
79                                v.val[c]=0;
80                        }
81                                               
82                        cvSet2D(m_Image,y,x,v);
83                }
84        }
85}
86
87Image Image::operator-(const Image &other)
88{
89        assert(other.m_Image->width == m_Image->width);
90        assert(other.m_Image->height == m_Image->height);
91        assert(other.m_Image->nChannels == m_Image->nChannels);
92
93        Image ret(*this);
94
95    for(int y=0; y<m_Image->height; y++)
96        {
97        for(int x=0; x<m_Image->width; x++)
98                {
99                        CvScalar v;
100                        v.val[0]=0;v.val[1]=0;v.val[2]=0;v.val[3]=0;
101                        for (int c=0; c<m_Image->nChannels; c++)
102                        {
103                                v.val[c]=abs((int)(cvGet2D(m_Image,y,x).val[c] -
104                                                   cvGet2D(other.m_Image,y,x).val[c]));         
105                        }
106                        cvSet2D(ret.m_Image,y,x,v);
107                }
108        }
109        return ret;
110}
111
112Image Image::operator+(const Image &other)
113{
114        assert(other.m_Image->width == m_Image->width);
115        assert(other.m_Image->height == m_Image->height);
116        assert(other.m_Image->nChannels == m_Image->nChannels);
117
118        Image ret(*this);
119
120    for(int y=0; y<m_Image->height; y++)
121        {
122        for(int x=0; x<m_Image->width; x++)
123                {
124                        CvScalar v;
125                        for (int c=0; c<m_Image->nChannels; c++)
126                        {
127                                v.val[c]=cvGet2D(m_Image,y,x).val[c] +
128                                         cvGet2D(other.m_Image,y,x).val[c];             
129                        }
130                        cvSet2D(&ret,y,x,v);
131                }
132        }
133       
134        return ret;
135}
136
137Image &Image::operator=(const Image &other)
138{
139        m_Image=cvCloneImage(other.m_Image);
140        return *this;
141}
142
143// safe accessor, which returns 0 if out of range
144unsigned char Image::SafeGet2D(int y, int x, int c)
145{
146        if (x<0 || x>=m_Image->width || y<0 || y>=m_Image->height)
147        {
148                return 0;
149        }
150       
151        return cvGet2D(m_Image,y,x).val[c];
152}
153
154void Image::PrintInfo()
155{
156        cerr<<m_Image->width<<"x"<<m_Image->height<<"x"<<m_Image->nChannels
157                <<" @ "<<m_Image->depth<<" bpp"<<endl;
158}
159
160void Image::Crop(int x, int y, int w, int h)
161{
162        CvRect roi;
163        roi.x=x;
164        roi.y=y;
165        roi.width=w;
166        roi.height=h;
167        IplImage *newimage;
168        cvSetImageROI(m_Image,roi);
169        newimage = cvCreateImage( cvSize(roi.width, roi.height), m_Image->depth, m_Image->nChannels );
170        cvCopy(m_Image,newimage);
171        cvReleaseImage(&m_Image);
172        m_Image=newimage;
173}
174
175Image Image::SubImage(int x, int y, int w, int h)
176{
177        CvRect roi;
178        roi.x=x;
179        roi.y=y;
180        roi.width=w;
181        roi.height=h;
182        IplImage *newimage;
183        cvSetImageROI(m_Image,roi);
184        newimage = cvCreateImage( cvSize(roi.width, roi.height), m_Image->depth, m_Image->nChannels );
185        cvCopy(m_Image,newimage);       
186        cvResetImageROI(m_Image);
187        return newimage;
188}
189
190Image Image::GRAY2RGB()
191{
192        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 3);
193    cvCvtColor(m_Image, newimage, CV_GRAY2RGB);
194        return Image(newimage);
195}
196
197Image Image::RGB2GRAY()
198{
199        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 1);
200    cvCvtColor(m_Image, newimage, CV_RGB2GRAY);
201        return Image(newimage);
202}
203
204Image Image::BayerGB2RGB()
205{
206        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 3);
207    cvCvtColor(m_Image, newimage, CV_BayerGB2RGB);
208        return Image(newimage);
209}
210
211Image Image::Scale(int w, int h)
212{
213        IplImage *newimage = cvCreateImage(cvSize(w,h), m_Image->depth, m_Image->nChannels);
214        cvResize( m_Image, newimage, CV_INTER_LINEAR );
215        return Image(newimage);
216}
217
218void Image::Blit(const Image &image, int px, int py)
219{       
220        for(int y=0; y<image.m_Image->height; y++)
221        {
222        for(int x=0; x<image.m_Image->width; x++)
223                {
224                        if (x+px>0 && x+px<m_Image->width &&
225                                y+py>0 && y+py<m_Image->height)
226                        {
227                if (image.m_Image->nChannels==1)
228                                {
229                                        CvScalar v;
230                                        v.val[0]=cvGet2D(image.m_Image,y,x).val[0];
231                                        v.val[1]=cvGet2D(image.m_Image,y,x).val[0];
232                                        v.val[2]=cvGet2D(image.m_Image,y,x).val[0];
233                        cvSet2D(m_Image,y+py,x+px,v);
234                                }
235                                else
236                                {
237                                        cvSet2D(m_Image,y+py,x+px,cvGet2D(image.m_Image,y,x));
238                                }
239                        }
240                }
241        }
242}
243
244void Image::SubMean()
245{       
246        // get the mean of each channel
247        CvScalar v;
248        for (int c=0; c<m_Image->nChannels; c++)
249        {
250                v.val[c]=0;
251        }
252
253        float s=m_Image->width*m_Image->height;
254
255    for(int y=0; y<m_Image->height; y++)
256        {
257        for(int x=0; x<m_Image->width; x++)
258                {
259                        for (int c=0; c<m_Image->nChannels; c++)
260                        {
261                                v.val[c]+=cvGet2D(m_Image,y,x).val[c]/256.0f;
262                        }
263                }
264        }
265       
266        for (int c=0; c<m_Image->nChannels; c++)
267        {
268                v.val[c]/=s;
269        }
270               
271        CvScalar o;
272       
273        // now subtract it from each pixel
274        for(int y=0; y<m_Image->height; y++)
275        {
276        for(int x=0; x<m_Image->width; x++)
277                {                       
278                        for (int c=0; c<m_Image->nChannels; c++)
279                        {
280                                // force the average to be 127
281                                o.val[c]=127+(cvGet2D(m_Image,y,x).val[c] - v.val[c]*256.0f);
282                        }
283                               
284            cvSet2D(m_Image,y,x,o);
285                }
286        }
287}
288
289float Image::SSD(Image &other)
290{
291        assert(other.m_Image->width == m_Image->width);
292        assert(other.m_Image->height == m_Image->height);
293       
294        float ret=0;
295        float dif=0;
296       
297    for(int y=0; y<m_Image->height; y++)
298        {
299        for(int x=0; x<m_Image->width; x++)
300                {
301                        for (int c=0; c<m_Image->nChannels; c++)
302                        {
303                                dif = (cvGet2D(m_Image,y,x).val[c]/256.0f) -
304                                      (cvGet2D(other.m_Image,y,x).val[c]/256.0f);
305                ret+=dif*dif;
306            }
307                }
308        }
309       
310        // not sure strictly whether the difference should be
311        // invariant to the number of pixels, but it helps
312        ret/=m_Image->width*m_Image->height*m_Image->nChannels;
313       
314        return ret;
315}
316
317void Image::LBP()
318{
319        IplImage *newimage;
320        newimage = cvCreateImage(cvGetSize(m_Image), m_Image->depth, m_Image->nChannels);
321               
322    // for each pixel
323    for(int y=0; y<m_Image->height; y++)
324        {
325        for(int x=0; x<m_Image->width; x++)
326                {
327                        CvScalar sc;
328                       
329                        // for each channel
330                        for(int c=0; c<m_Image->nChannels; c++)
331                        {
332                                unsigned char v=0;
333                                unsigned char o=cvGet2D(m_Image,y,x).val[c];
334                                unsigned char b=0;
335
336                                // loop through a 3x3 kernel
337                                for (int kx=-1; kx<=1; kx++)
338                                {
339                                        for (int ky=-1; ky<=1; ky++)
340                                        {
341                                                // don't compare with ourself
342                                                if (!(kx==0 && ky==0))
343                                                {
344                                                        // threshold
345                                                        if (o>SafeGet2D(y+ky,x+kx,c))
346                                                        {
347                                                                // bit magic
348                                                                v|=(1<<b);
349                                                        }
350                                                        b++;
351                                                }
352                                        }
353                                }
354                                sc.val[c]=v;
355                        }
356                        cvSet2D(newimage,y,x,sc);
357                }
358        }
359       
360        cvReleaseImage(&m_Image);
361        m_Image=newimage;
362}
363
364unsigned int *Image::Hist(int channel)
365{
366        assert(channel<m_Image->nChannels);
367        assert(m_Image->depth == 8);
368       
369        unsigned int *h=new unsigned int[256];
370
371        for(int i=0; i<256; i++)
372        {
373                h[i]=0;
374        }
375
376    // for each pixel
377    for(int y=0; y<m_Image->height; y++)
378        {
379        for(int x=0; x<m_Image->width; x++)
380                {
381                        h[(unsigned char)cvGet2D(m_Image,y,x).val[channel]]++;
382                }
383        }
384       
385        return h;
386}
387
388Vector<float> Image::ToFloatVector()
389{
390        Vector<float> v(m_Image->width*m_Image->height*m_Image->nChannels);
391    // for each pixel
392        unsigned int pos=0;
393    for(int y=0; y<m_Image->height; y++)
394        {
395        for(int x=0; x<m_Image->width; x++)
396                {
397                        for (int c=0; c<m_Image->nChannels; c++)
398                        {
399                                v[pos++]=cvGet2D(m_Image,y,x).val[c]/256.0f;
400                        }
401                }
402        }
403        return v;
404}
Note: See TracBrowser for help on using the repository browser.