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

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

added face classifier application, not working yet

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        cvReleaseImage(&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        // now subtract it from each pixel
272        for(int y=0; y<m_Image->height; y++)
273        {
274        for(int x=0; x<m_Image->width; x++)
275                {
276                        for (int c=0; c<m_Image->nChannels; c++)
277                        {
278                                // force the average to be 127
279                                v.val[c]=127+(cvGet2D(m_Image,y,x).val[c] - v.val[c]*256.0f);
280                        }
281               
282            cvSet2D(m_Image,y,x,v);
283                }
284        }
285}
286
287float Image::SSD(Image &other)
288{
289        assert(other.m_Image->width == m_Image->width);
290        assert(other.m_Image->height == m_Image->height);
291       
292        float ret=0;
293        float dif=0;
294       
295    for(int y=0; y<m_Image->height; y++)
296        {
297        for(int x=0; x<m_Image->width; x++)
298                {
299                        for (int c=0; c<m_Image->nChannels; c++)
300                        {
301                                dif = (cvGet2D(m_Image,y,x).val[c]/256.0f) -
302                                      (cvGet2D(other.m_Image,y,x).val[c]/256.0f);
303                ret+=dif*dif;
304            }
305                }
306        }
307       
308        // not sure strictly whether the difference should be
309        // invariant to the number of pixels, but it helps
310        ret/=m_Image->width*m_Image->height*m_Image->nChannels;
311       
312        return ret;
313}
314
315void Image::LBP()
316{
317        IplImage *newimage;
318        newimage = cvCreateImage(cvGetSize(m_Image), m_Image->depth, m_Image->nChannels);
319               
320    // for each pixel
321    for(int y=0; y<m_Image->height; y++)
322        {
323        for(int x=0; x<m_Image->width; x++)
324                {
325                        CvScalar sc;
326                       
327                        // for each channel
328                        for(int c=0; c<m_Image->nChannels; c++)
329                        {
330                                unsigned char v=0;
331                                unsigned char o=cvGet2D(m_Image,y,x).val[c];
332                                unsigned char b=0;
333
334                                // loop through a 3x3 kernel
335                                for (int kx=-1; kx<=1; kx++)
336                                {
337                                        for (int ky=-1; ky<=1; ky++)
338                                        {
339                                                // don't compare with ourself
340                                                if (!(kx==0 && ky==0))
341                                                {
342                                                        // threshold
343                                                        if (o>SafeGet2D(y+ky,x+kx,c))
344                                                        {
345                                                                // bit magic
346                                                                v|=(1<<b);
347                                                        }
348                                                        b++;
349                                                }
350                                        }
351                                }
352                                sc.val[c]=v;
353                        }
354                        cvSet2D(newimage,y,x,sc);
355                }
356        }
357       
358        cvReleaseImage(&m_Image);
359        m_Image=newimage;
360}
361
362unsigned int *Image::Hist(int channel)
363{
364        assert(channel<m_Image->nChannels);
365        assert(m_Image->depth == 8);
366       
367        unsigned int *h=new unsigned int[256];
368
369        for(int i=0; i<256; i++)
370        {
371                h[i]=0;
372        }
373
374    // for each pixel
375    for(int y=0; y<m_Image->height; y++)
376        {
377        for(int x=0; x<m_Image->width; x++)
378                {
379                        h[(unsigned char)cvGet2D(m_Image,y,x).val[channel]]++;
380                }
381        }
382       
383        return h;
384}
385
386Vector<float> Image::ToFloatVector()
387{
388        Vector<float> v(m_Image->width*m_Image->height*m_Image->nChannels);
389    // for each pixel
390        unsigned int pos=0;
391    for(int y=0; y<m_Image->height; y++)
392        {
393        for(int x=0; x<m_Image->width; x++)
394                {
395                        for (int c=0; c<m_Image->nChannels; c++)
396                        {
397                                v[pos++]=cvGet2D(m_Image,y,x).val[c]/256.0f;
398                        }
399                }
400        }
401        return v;
402}
Note: See TracBrowser for help on using the repository browser.