source: libs/magicsquares/src/Image.cpp @ 1031

Revision 1031, 9.3 KB checked in by dave, 9 years ago (diff)

memory leak fix, and added documentation

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);
34cerr<<filename<<" "<<m_Image->nChannels<<endl;
35
36}
37
38Image::Image(const Image &other)
39{
40        m_Image=cvCloneImage(other.m_Image);
41}
42
43Image::Image(const IplImage *other)
44{
45        m_Image=cvCloneImage(other);
46}
47
48Image::Image(int w, int h, int c, const Vector<float> &v, float gain)
49{
50        m_Image=cvCreateImage(cvSize(w, h), 8, c);
51        unsigned int pos=0;
52        for(int y=0; y<m_Image->height; y++)
53        {
54        for(int x=0; x<m_Image->width; x++)
55                {
56                        CvScalar s;
57                        for (int c=0; c<m_Image->nChannels; c++)
58                        {
59                                s.val[c]=(0.5+v[pos++]*gain)*127.0f;
60                        }
61                        cvSet2D(m_Image,y,x,s);
62                }
63        }
64}
65
66Image::~Image()
67{
68        cvReleaseImage(&m_Image);
69}
70
71void Image::Clear()
72{
73    for(int y=0; y<m_Image->height; y++)
74        {
75        for(int x=0; x<m_Image->width; x++)
76                {
77                        CvScalar v;
78                       
79                        for (int c=0; c<m_Image->nChannels; c++)
80                        {
81                                v.val[c]=0;
82                        }
83                                               
84                        cvSet2D(m_Image,y,x,v);
85                }
86        }
87}
88
89Image Image::operator-(const Image &other)
90{
91        assert(other.m_Image->width == m_Image->width);
92        assert(other.m_Image->height == m_Image->height);
93        assert(other.m_Image->nChannels == m_Image->nChannels);
94
95        Image ret(*this);
96
97    for(int y=0; y<m_Image->height; y++)
98        {
99        for(int x=0; x<m_Image->width; x++)
100                {
101                        CvScalar v;
102                        v.val[0]=0;v.val[1]=0;v.val[2]=0;v.val[3]=0;
103                        for (int c=0; c<m_Image->nChannels; c++)
104                        {
105                                v.val[c]=abs((int)(cvGet2D(m_Image,y,x).val[c] -
106                                                   cvGet2D(other.m_Image,y,x).val[c]));         
107                        }
108                        cvSet2D(ret.m_Image,y,x,v);
109                }
110        }
111        return ret;
112}
113
114Image Image::operator+(const Image &other)
115{
116        assert(other.m_Image->width == m_Image->width);
117        assert(other.m_Image->height == m_Image->height);
118        assert(other.m_Image->nChannels == m_Image->nChannels);
119
120        Image ret(*this);
121
122    for(int y=0; y<m_Image->height; y++)
123        {
124        for(int x=0; x<m_Image->width; x++)
125                {
126                        CvScalar v;
127                        for (int c=0; c<m_Image->nChannels; c++)
128                        {
129                                v.val[c]=cvGet2D(m_Image,y,x).val[c] +
130                                         cvGet2D(other.m_Image,y,x).val[c];             
131                        }
132                        cvSet2D(&ret,y,x,v);
133                }
134        }
135       
136        return ret;
137}
138
139Image &Image::operator=(const Image &other)
140{
141        if (m_Image!=NULL) cvReleaseImage(&m_Image);
142        m_Image=cvCloneImage(other.m_Image);
143        return *this;
144}
145
146// safe accessor, which returns 0 if out of range
147unsigned char Image::SafeGet2D(int y, int x, int c)
148{
149        if (x<0 || x>=m_Image->width || y<0 || y>=m_Image->height)
150        {
151                return 0;
152        }
153       
154        return cvGet2D(m_Image,y,x).val[c];
155}
156
157void Image::PrintInfo()
158{
159        cerr<<m_Image->width<<"x"<<m_Image->height<<"x"<<m_Image->nChannels
160                <<" @ "<<m_Image->depth<<" bpp"<<endl;
161}
162
163void Image::Crop(int x, int y, int w, int h)
164{
165        CvRect roi;
166        roi.x=x;
167        roi.y=y;
168        roi.width=w;
169        roi.height=h;
170        IplImage *newimage;
171        cvSetImageROI(m_Image,roi);
172        newimage = cvCreateImage( cvSize(roi.width, roi.height), m_Image->depth, m_Image->nChannels );
173        cvCopy(m_Image,newimage);
174        cvReleaseImage(&m_Image);
175        m_Image=newimage;
176}
177
178Image Image::SubImage(Rect r)
179{
180        return SubImage(r.x, r.y, r.w, r.h);
181}
182
183Image Image::SubImage(int x, int y, int w, int h)
184{
185        CvRect roi;
186        roi.x=x;
187        roi.y=y;
188        roi.width=w;
189        roi.height=h;
190        IplImage *newimage;
191        cvSetImageROI(m_Image,roi);
192        newimage = cvCreateImage( cvSize(roi.width, roi.height), m_Image->depth, m_Image->nChannels );
193        cvCopy(m_Image,newimage);       
194        cvResetImageROI(m_Image);
195        Image ret(newimage);
196    cvReleaseImage(&newimage);
197    return ret;
198}
199
200Image Image::GRAY2RGB()
201{
202        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 3);
203    cvCvtColor(m_Image, newimage, CV_GRAY2RGB);
204        Image ret(newimage);
205    cvReleaseImage(&newimage);
206    return ret;
207}
208
209Image Image::RGB2GRAY()
210{
211        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 1);
212    cvCvtColor(m_Image, newimage, CV_RGB2GRAY);
213        Image ret(newimage);
214    cvReleaseImage(&newimage);
215    return ret;
216}
217
218Image Image::BayerGB2RGB()
219{
220        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 3);
221    cvCvtColor(m_Image, newimage, CV_BayerGB2RGB);
222        Image ret(newimage);
223    cvReleaseImage(&newimage);
224    return ret;
225}
226
227Image Image::Scale(int w, int h)
228{
229        IplImage *newimage = cvCreateImage(cvSize(w,h), m_Image->depth, m_Image->nChannels);
230        cvResize( m_Image, newimage, CV_INTER_LINEAR );
231        Image ret(newimage);
232    cvReleaseImage(&newimage);
233    return ret;
234}
235
236void Image::Blit(const Image &image, int px, int py)
237{       
238        for(int y=0; y<image.m_Image->height; y++)
239        {
240        for(int x=0; x<image.m_Image->width; x++)
241                {
242                        if (x+px>0 && x+px<m_Image->width &&
243                                y+py>0 && y+py<m_Image->height)
244                        {
245                if (image.m_Image->nChannels==1)
246                                {
247                                        CvScalar v;
248                                        v.val[0]=cvGet2D(image.m_Image,y,x).val[0];
249                                        v.val[1]=cvGet2D(image.m_Image,y,x).val[0];
250                                        v.val[2]=cvGet2D(image.m_Image,y,x).val[0];
251                        cvSet2D(m_Image,y+py,x+px,v);
252                                }
253                                else
254                                {
255                                        cvSet2D(m_Image,y+py,x+px,cvGet2D(image.m_Image,y,x));
256                                }
257                        }
258                }
259        }
260}
261
262void Image::SubMean()
263{       
264        // get the mean of each channel
265        CvScalar v;
266        for (int c=0; c<m_Image->nChannels; c++)
267        {
268                v.val[c]=0;
269        }
270
271        float s=m_Image->width*m_Image->height;
272
273    for(int y=0; y<m_Image->height; y++)
274        {
275        for(int x=0; x<m_Image->width; x++)
276                {
277                        for (int c=0; c<m_Image->nChannels; c++)
278                        {
279                                v.val[c]+=cvGet2D(m_Image,y,x).val[c]/256.0f;
280                        }
281                }
282        }
283       
284        for (int c=0; c<m_Image->nChannels; c++)
285        {
286                v.val[c]/=s;
287        }
288               
289        CvScalar o;
290       
291        // now subtract it from each pixel
292        for(int y=0; y<m_Image->height; y++)
293        {
294        for(int x=0; x<m_Image->width; x++)
295                {                       
296                        for (int c=0; c<m_Image->nChannels; c++)
297                        {
298                                // force the average to be 127
299                                o.val[c]=127+(cvGet2D(m_Image,y,x).val[c] - v.val[c]*256.0f);
300                        }
301                               
302            cvSet2D(m_Image,y,x,o);
303                }
304        }
305}
306
307float Image::SSD(Image &other)
308{
309        assert(other.m_Image->width == m_Image->width);
310        assert(other.m_Image->height == m_Image->height);
311       
312        float ret=0;
313        float dif=0;
314       
315    for(int y=0; y<m_Image->height; y++)
316        {
317        for(int x=0; x<m_Image->width; x++)
318                {
319                        for (int c=0; c<m_Image->nChannels; c++)
320                        {
321                                dif = (cvGet2D(m_Image,y,x).val[c]/256.0f) -
322                                      (cvGet2D(other.m_Image,y,x).val[c]/256.0f);
323                ret+=dif*dif;
324            }
325                }
326        }
327       
328        // not sure strictly whether the difference should be
329        // invariant to the number of pixels, but it helps
330        ret/=m_Image->width*m_Image->height*m_Image->nChannels;
331       
332        return ret;
333}
334
335void Image::LBP()
336{
337        IplImage *newimage;
338        newimage = cvCreateImage(cvGetSize(m_Image), m_Image->depth, m_Image->nChannels);
339               
340    // for each pixel
341    for(int y=0; y<m_Image->height; y++)
342        {
343        for(int x=0; x<m_Image->width; x++)
344                {
345                        CvScalar sc;
346                       
347                        // for each channel
348                        for(int c=0; c<m_Image->nChannels; c++)
349                        {
350                                unsigned char v=0;
351                                unsigned char o=cvGet2D(m_Image,y,x).val[c];
352                                unsigned char b=0;
353
354                                // loop through a 3x3 kernel
355                                for (int kx=-1; kx<=1; kx++)
356                                {
357                                        for (int ky=-1; ky<=1; ky++)
358                                        {
359                                                // don't compare with ourself
360                                                if (!(kx==0 && ky==0))
361                                                {
362                                                        // threshold
363                                                        if (o>SafeGet2D(y+ky,x+kx,c))
364                                                        {
365                                                                // bit magic
366                                                                v|=(1<<b);
367                                                        }
368                                                        b++;
369                                                }
370                                        }
371                                }
372                                sc.val[c]=v;
373                        }
374                        cvSet2D(newimage,y,x,sc);
375                }
376        }
377       
378        cvReleaseImage(&m_Image);
379        m_Image=newimage;
380}
381
382unsigned int *Image::Hist(int channel)
383{
384        assert(channel<m_Image->nChannels);
385        assert(m_Image->depth == 8);
386       
387        unsigned int *h=new unsigned int[256];
388
389        for(int i=0; i<256; i++)
390        {
391                h[i]=0;
392        }
393
394    // for each pixel
395    for(int y=0; y<m_Image->height; y++)
396        {
397        for(int x=0; x<m_Image->width; x++)
398                {
399                        h[(unsigned char)cvGet2D(m_Image,y,x).val[channel]]++;
400                }
401        }
402       
403        return h;
404}
405
406Vector<float> Image::ToFloatVector()
407{
408        Vector<float> v(m_Image->width*m_Image->height*m_Image->nChannels);
409    // for each pixel
410        unsigned int pos=0;
411    for(int y=0; y<m_Image->height; y++)
412        {
413        for(int x=0; x<m_Image->width; x++)
414                {
415                        for (int c=0; c<m_Image->nChannels; c++)
416                        {
417                                v[pos++]=cvGet2D(m_Image,y,x).val[c]/256.0f;
418                        }
419                }
420        }
421        return v;
422}
423
424void Image::Save(const string &filename)
425{
426        cvSaveImage(filename.c_str(),m_Image);
427}
428
429void Image::GetBB(int thresh, int &minx, int &miny, int &maxx, int &maxy)
430{
431    minx=m_Image->width;
432    miny=m_Image->height;
433    maxx=0;
434    maxy=0;
435
436    for(int y=0; y<m_Image->height; y++)
437        {
438        for(int x=0; x<m_Image->width; x++)
439                {
440            if (cvGet2D(m_Image,y,x).val[0]>thresh)
441            {
442                if (x<minx) minx=x;           
443                if (y<miny) miny=y;
444                if (x>maxx) maxx=x;           
445                if (y>maxy) maxy=y;
446            }
447        }
448    }
449}
Note: See TracBrowser for help on using the repository browser.