source: libs/suds/src/Image.cpp @ 204

Revision 204, 8.5 KB checked in by dave, 10 years ago (diff)

added dot product

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        m_Image=cvCloneImage(other.m_Image);
142        return *this;
143}
144
145// safe accessor, which returns 0 if out of range
146unsigned char Image::SafeGet2D(int y, int x, int c)
147{
148        if (x<0 || x>=m_Image->width || y<0 || y>=m_Image->height)
149        {
150                return 0;
151        }
152       
153        return cvGet2D(m_Image,y,x).val[c];
154}
155
156void Image::PrintInfo()
157{
158        cerr<<m_Image->width<<"x"<<m_Image->height<<"x"<<m_Image->nChannels
159                <<" @ "<<m_Image->depth<<" bpp"<<endl;
160}
161
162void Image::Crop(int x, int y, int w, int h)
163{
164        CvRect roi;
165        roi.x=x;
166        roi.y=y;
167        roi.width=w;
168        roi.height=h;
169        IplImage *newimage;
170        cvSetImageROI(m_Image,roi);
171        newimage = cvCreateImage( cvSize(roi.width, roi.height), m_Image->depth, m_Image->nChannels );
172        cvCopy(m_Image,newimage);
173        cvReleaseImage(&m_Image);
174        m_Image=newimage;
175}
176
177Image Image::SubImage(Rect r)
178{
179        return SubImage(r.x, r.y, r.w, r.h);
180}
181
182Image Image::SubImage(int x, int y, int w, int h)
183{
184        CvRect roi;
185        roi.x=x;
186        roi.y=y;
187        roi.width=w;
188        roi.height=h;
189        IplImage *newimage;
190        cvSetImageROI(m_Image,roi);
191        newimage = cvCreateImage( cvSize(roi.width, roi.height), m_Image->depth, m_Image->nChannels );
192        cvCopy(m_Image,newimage);       
193        cvResetImageROI(m_Image);
194        return newimage;
195}
196
197Image Image::GRAY2RGB()
198{
199        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 3);
200    cvCvtColor(m_Image, newimage, CV_GRAY2RGB);
201        return Image(newimage);
202}
203
204Image Image::RGB2GRAY()
205{
206        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 1);
207    cvCvtColor(m_Image, newimage, CV_RGB2GRAY);
208        return Image(newimage);
209}
210
211Image Image::BayerGB2RGB()
212{
213        IplImage *newimage = cvCreateImage(cvGetSize(m_Image), 8, 3);
214    cvCvtColor(m_Image, newimage, CV_BayerGB2RGB);
215        return Image(newimage);
216}
217
218Image Image::Scale(int w, int h)
219{
220        IplImage *newimage = cvCreateImage(cvSize(w,h), m_Image->depth, m_Image->nChannels);
221        cvResize( m_Image, newimage, CV_INTER_LINEAR );
222        return Image(newimage);
223}
224
225void Image::Blit(const Image &image, int px, int py)
226{       
227        for(int y=0; y<image.m_Image->height; y++)
228        {
229        for(int x=0; x<image.m_Image->width; x++)
230                {
231                        if (x+px>0 && x+px<m_Image->width &&
232                                y+py>0 && y+py<m_Image->height)
233                        {
234                if (image.m_Image->nChannels==1)
235                                {
236                                        CvScalar v;
237                                        v.val[0]=cvGet2D(image.m_Image,y,x).val[0];
238                                        v.val[1]=cvGet2D(image.m_Image,y,x).val[0];
239                                        v.val[2]=cvGet2D(image.m_Image,y,x).val[0];
240                        cvSet2D(m_Image,y+py,x+px,v);
241                                }
242                                else
243                                {
244                                        cvSet2D(m_Image,y+py,x+px,cvGet2D(image.m_Image,y,x));
245                                }
246                        }
247                }
248        }
249}
250
251void Image::SubMean()
252{       
253        // get the mean of each channel
254        CvScalar v;
255        for (int c=0; c<m_Image->nChannels; c++)
256        {
257                v.val[c]=0;
258        }
259
260        float s=m_Image->width*m_Image->height;
261
262    for(int y=0; y<m_Image->height; y++)
263        {
264        for(int x=0; x<m_Image->width; x++)
265                {
266                        for (int c=0; c<m_Image->nChannels; c++)
267                        {
268                                v.val[c]+=cvGet2D(m_Image,y,x).val[c]/256.0f;
269                        }
270                }
271        }
272       
273        for (int c=0; c<m_Image->nChannels; c++)
274        {
275                v.val[c]/=s;
276        }
277               
278        CvScalar o;
279       
280        // now subtract it from each pixel
281        for(int y=0; y<m_Image->height; y++)
282        {
283        for(int x=0; x<m_Image->width; x++)
284                {                       
285                        for (int c=0; c<m_Image->nChannels; c++)
286                        {
287                                // force the average to be 127
288                                o.val[c]=127+(cvGet2D(m_Image,y,x).val[c] - v.val[c]*256.0f);
289                        }
290                               
291            cvSet2D(m_Image,y,x,o);
292                }
293        }
294}
295
296float Image::SSD(Image &other)
297{
298        assert(other.m_Image->width == m_Image->width);
299        assert(other.m_Image->height == m_Image->height);
300       
301        float ret=0;
302        float dif=0;
303       
304    for(int y=0; y<m_Image->height; y++)
305        {
306        for(int x=0; x<m_Image->width; x++)
307                {
308                        for (int c=0; c<m_Image->nChannels; c++)
309                        {
310                                dif = (cvGet2D(m_Image,y,x).val[c]/256.0f) -
311                                      (cvGet2D(other.m_Image,y,x).val[c]/256.0f);
312                ret+=dif*dif;
313            }
314                }
315        }
316       
317        // not sure strictly whether the difference should be
318        // invariant to the number of pixels, but it helps
319        ret/=m_Image->width*m_Image->height*m_Image->nChannels;
320       
321        return ret;
322}
323
324void Image::LBP()
325{
326        IplImage *newimage;
327        newimage = cvCreateImage(cvGetSize(m_Image), m_Image->depth, m_Image->nChannels);
328               
329    // for each pixel
330    for(int y=0; y<m_Image->height; y++)
331        {
332        for(int x=0; x<m_Image->width; x++)
333                {
334                        CvScalar sc;
335                       
336                        // for each channel
337                        for(int c=0; c<m_Image->nChannels; c++)
338                        {
339                                unsigned char v=0;
340                                unsigned char o=cvGet2D(m_Image,y,x).val[c];
341                                unsigned char b=0;
342
343                                // loop through a 3x3 kernel
344                                for (int kx=-1; kx<=1; kx++)
345                                {
346                                        for (int ky=-1; ky<=1; ky++)
347                                        {
348                                                // don't compare with ourself
349                                                if (!(kx==0 && ky==0))
350                                                {
351                                                        // threshold
352                                                        if (o>SafeGet2D(y+ky,x+kx,c))
353                                                        {
354                                                                // bit magic
355                                                                v|=(1<<b);
356                                                        }
357                                                        b++;
358                                                }
359                                        }
360                                }
361                                sc.val[c]=v;
362                        }
363                        cvSet2D(newimage,y,x,sc);
364                }
365        }
366       
367        cvReleaseImage(&m_Image);
368        m_Image=newimage;
369}
370
371unsigned int *Image::Hist(int channel)
372{
373        assert(channel<m_Image->nChannels);
374        assert(m_Image->depth == 8);
375       
376        unsigned int *h=new unsigned int[256];
377
378        for(int i=0; i<256; i++)
379        {
380                h[i]=0;
381        }
382
383    // for each pixel
384    for(int y=0; y<m_Image->height; y++)
385        {
386        for(int x=0; x<m_Image->width; x++)
387                {
388                        h[(unsigned char)cvGet2D(m_Image,y,x).val[channel]]++;
389                }
390        }
391       
392        return h;
393}
394
395Vector<float> Image::ToFloatVector()
396{
397        Vector<float> v(m_Image->width*m_Image->height*m_Image->nChannels);
398    // for each pixel
399        unsigned int pos=0;
400    for(int y=0; y<m_Image->height; y++)
401        {
402        for(int x=0; x<m_Image->width; x++)
403                {
404                        for (int c=0; c<m_Image->nChannels; c++)
405                        {
406                                v[pos++]=cvGet2D(m_Image,y,x).val[c]/256.0f;
407                        }
408                }
409        }
410        return v;
411}
412
413void Image::Save(const string &filename)
414{
415        cvSaveImage(filename.c_str(),m_Image);
416}
417
Note: See TracBrowser for help on using the repository browser.