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

Revision 784, 9.2 KB checked in by dave, 9 years ago (diff)

fixed memory leak
M magicsquares/src/Image.cpp

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        return newimage;
196}
197
198Image Image::GRAY2RGB()
199{
200        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 3);
201    cvCvtColor(m_Image, newimage, CV_GRAY2RGB);
202        Image ret(newimage);
203    cvReleaseImage(&newimage);
204    return ret;
205}
206
207Image Image::RGB2GRAY()
208{
209        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 1);
210    cvCvtColor(m_Image, newimage, CV_RGB2GRAY);
211        Image ret(newimage);
212    cvReleaseImage(&newimage);
213    return ret;
214}
215
216Image Image::BayerGB2RGB()
217{
218        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 3);
219    cvCvtColor(m_Image, newimage, CV_BayerGB2RGB);
220        Image ret(newimage);
221    cvReleaseImage(&newimage);
222    return ret;
223}
224
225Image Image::Scale(int w, int h)
226{
227        IplImage *newimage = cvCreateImage(cvSize(w,h), m_Image->depth, m_Image->nChannels);
228        cvResize( m_Image, newimage, CV_INTER_LINEAR );
229        Image ret(newimage);
230    cvReleaseImage(&newimage);
231    return ret;
232}
233
234void Image::Blit(const Image &image, int px, int py)
235{       
236        for(int y=0; y<image.m_Image->height; y++)
237        {
238        for(int x=0; x<image.m_Image->width; x++)
239                {
240                        if (x+px>0 && x+px<m_Image->width &&
241                                y+py>0 && y+py<m_Image->height)
242                        {
243                if (image.m_Image->nChannels==1)
244                                {
245                                        CvScalar v;
246                                        v.val[0]=cvGet2D(image.m_Image,y,x).val[0];
247                                        v.val[1]=cvGet2D(image.m_Image,y,x).val[0];
248                                        v.val[2]=cvGet2D(image.m_Image,y,x).val[0];
249                        cvSet2D(m_Image,y+py,x+px,v);
250                                }
251                                else
252                                {
253                                        cvSet2D(m_Image,y+py,x+px,cvGet2D(image.m_Image,y,x));
254                                }
255                        }
256                }
257        }
258}
259
260void Image::SubMean()
261{       
262        // get the mean of each channel
263        CvScalar v;
264        for (int c=0; c<m_Image->nChannels; c++)
265        {
266                v.val[c]=0;
267        }
268
269        float s=m_Image->width*m_Image->height;
270
271    for(int y=0; y<m_Image->height; y++)
272        {
273        for(int x=0; x<m_Image->width; x++)
274                {
275                        for (int c=0; c<m_Image->nChannels; c++)
276                        {
277                                v.val[c]+=cvGet2D(m_Image,y,x).val[c]/256.0f;
278                        }
279                }
280        }
281       
282        for (int c=0; c<m_Image->nChannels; c++)
283        {
284                v.val[c]/=s;
285        }
286               
287        CvScalar o;
288       
289        // now subtract it from each pixel
290        for(int y=0; y<m_Image->height; y++)
291        {
292        for(int x=0; x<m_Image->width; x++)
293                {                       
294                        for (int c=0; c<m_Image->nChannels; c++)
295                        {
296                                // force the average to be 127
297                                o.val[c]=127+(cvGet2D(m_Image,y,x).val[c] - v.val[c]*256.0f);
298                        }
299                               
300            cvSet2D(m_Image,y,x,o);
301                }
302        }
303}
304
305float Image::SSD(Image &other)
306{
307        assert(other.m_Image->width == m_Image->width);
308        assert(other.m_Image->height == m_Image->height);
309       
310        float ret=0;
311        float dif=0;
312       
313    for(int y=0; y<m_Image->height; y++)
314        {
315        for(int x=0; x<m_Image->width; x++)
316                {
317                        for (int c=0; c<m_Image->nChannels; c++)
318                        {
319                                dif = (cvGet2D(m_Image,y,x).val[c]/256.0f) -
320                                      (cvGet2D(other.m_Image,y,x).val[c]/256.0f);
321                ret+=dif*dif;
322            }
323                }
324        }
325       
326        // not sure strictly whether the difference should be
327        // invariant to the number of pixels, but it helps
328        ret/=m_Image->width*m_Image->height*m_Image->nChannels;
329       
330        return ret;
331}
332
333void Image::LBP()
334{
335        IplImage *newimage;
336        newimage = cvCreateImage(cvGetSize(m_Image), m_Image->depth, m_Image->nChannels);
337               
338    // for each pixel
339    for(int y=0; y<m_Image->height; y++)
340        {
341        for(int x=0; x<m_Image->width; x++)
342                {
343                        CvScalar sc;
344                       
345                        // for each channel
346                        for(int c=0; c<m_Image->nChannels; c++)
347                        {
348                                unsigned char v=0;
349                                unsigned char o=cvGet2D(m_Image,y,x).val[c];
350                                unsigned char b=0;
351
352                                // loop through a 3x3 kernel
353                                for (int kx=-1; kx<=1; kx++)
354                                {
355                                        for (int ky=-1; ky<=1; ky++)
356                                        {
357                                                // don't compare with ourself
358                                                if (!(kx==0 && ky==0))
359                                                {
360                                                        // threshold
361                                                        if (o>SafeGet2D(y+ky,x+kx,c))
362                                                        {
363                                                                // bit magic
364                                                                v|=(1<<b);
365                                                        }
366                                                        b++;
367                                                }
368                                        }
369                                }
370                                sc.val[c]=v;
371                        }
372                        cvSet2D(newimage,y,x,sc);
373                }
374        }
375       
376        cvReleaseImage(&m_Image);
377        m_Image=newimage;
378}
379
380unsigned int *Image::Hist(int channel)
381{
382        assert(channel<m_Image->nChannels);
383        assert(m_Image->depth == 8);
384       
385        unsigned int *h=new unsigned int[256];
386
387        for(int i=0; i<256; i++)
388        {
389                h[i]=0;
390        }
391
392    // for each pixel
393    for(int y=0; y<m_Image->height; y++)
394        {
395        for(int x=0; x<m_Image->width; x++)
396                {
397                        h[(unsigned char)cvGet2D(m_Image,y,x).val[channel]]++;
398                }
399        }
400       
401        return h;
402}
403
404Vector<float> Image::ToFloatVector()
405{
406        Vector<float> v(m_Image->width*m_Image->height*m_Image->nChannels);
407    // for each pixel
408        unsigned int pos=0;
409    for(int y=0; y<m_Image->height; y++)
410        {
411        for(int x=0; x<m_Image->width; x++)
412                {
413                        for (int c=0; c<m_Image->nChannels; c++)
414                        {
415                                v[pos++]=cvGet2D(m_Image,y,x).val[c]/256.0f;
416                        }
417                }
418        }
419        return v;
420}
421
422void Image::Save(const string &filename)
423{
424        cvSaveImage(filename.c_str(),m_Image);
425}
426
427void Image::GetBB(int thresh, int &minx, int &miny, int &maxx, int &maxy)
428{
429    minx=m_Image->width;
430    miny=m_Image->height;
431    maxx=0;
432    maxy=0;
433
434    for(int y=0; y<m_Image->height; y++)
435        {
436        for(int x=0; x<m_Image->width; x++)
437                {
438            if (cvGet2D(m_Image,y,x).val[0]>thresh)
439            {
440                if (x<minx) minx=x;           
441                if (y<miny) miny=y;
442                if (x>maxx) maxx=x;           
443                if (y>maxy) maxy=y;
444            }
445        }
446    }
447}
Note: See TracBrowser for help on using the repository browser.