Move the sources to trunk
[opencv] / apps / VMDemo / SubdivMorpher.h
1 #pragma once
2
3 #include "cv.h"
4 #include "cvaux.h"
5 #include <assert.h>
6 #include <string.h>
7 #include <stdlib.h>
8
9 inline CvSize GetImageSize( IplImage* img )
10 {
11     CvSize size = { 0, 0 };
12     if( img ) cvGetImageRawData( img, 0, 0, &size );
13     return size;
14 }
15
16
17 inline IplImage* CreateIsometricImage( IplImage* src, IplImage* dst,
18                                        int desired_depth, int desired_num_channels )
19 {
20     CvSize src_size = GetImageSize( src ),
21            dst_size = src_size;
22
23     if( dst ) dst_size = GetImageSize( dst );
24
25     if( !dst || dst->depth != desired_depth ||
26         dst->nChannels != desired_num_channels ||
27         dst_size.width != src_size.width ||
28         dst_size.height != dst_size.height )
29     {
30         cvReleaseImage( &dst );
31         dst = cvCreateImage( src_size, desired_depth, desired_num_channels );
32     }
33
34     return dst;
35 }
36
37 // Basic class for ViewMorphing
38 class CCvMorpher
39 {
40 protected:
41
42     IplImage* m_left_img;
43     IplImage* m_right_img;
44     IplImage* m_virtual_img;
45     IplImage* m_disparity_img;
46
47     float     m_pan;
48     bool      m_isVirtualImageReady;
49     bool      m_isStereoReady;
50     bool      m_isDisparityReady;
51
52     void  Clear()
53     {
54         m_left_img = m_right_img = m_virtual_img = m_disparity_img = 0;
55         m_pan = 0.5f;
56         m_isVirtualImageReady = m_isStereoReady =
57             m_isDisparityReady = false;
58     }
59
60     virtual void  ResetStereo()
61     {
62         m_isVirtualImageReady = m_isStereoReady =
63             m_isDisparityReady = false;
64     }
65
66     virtual void  Release()
67     {
68         cvReleaseImage( &m_left_img );
69         cvReleaseImage( &m_right_img );
70         cvReleaseImage( &m_virtual_img );
71         cvReleaseImage( &m_disparity_img );
72         Clear();
73     }
74
75     virtual bool  OnCalculateStereo()
76     {
77         return false;
78     }
79
80     virtual bool  OnCalculateVirtualImage()
81     {
82         return false;
83     }
84
85     virtual bool  CalculateStereo()
86     {
87         CvSize left_size = GetImageSize(m_left_img),
88                right_size = GetImageSize(m_right_img);
89         
90         if( !m_left_img || !m_right_img ||
91             m_left_img->depth != m_right_img->depth ||
92             m_left_img->depth != IPL_DEPTH_8U ||
93             m_left_img->nChannels != m_right_img->nChannels ||
94             m_left_img->nChannels != 3 ||
95             left_size.width != right_size.width ||
96             left_size.height != right_size.height ) return false;
97
98         return OnCalculateStereo();
99     }
100
101     virtual bool  CalculateVirtualImage()
102     {
103         m_virtual_img = CreateIsometricImage( m_left_img,
104                                               m_virtual_img,
105                                               m_left_img -> depth,
106                                               m_left_img -> nChannels
107                                             );
108         return OnCalculateVirtualImage();
109     }
110
111     virtual bool OnCalculateDisparity()
112     {
113         return false;
114     }
115
116     virtual bool CalculateDisparity()
117     {
118         if( !m_isStereoReady )
119         {
120             m_isStereoReady = CalculateStereo();
121         }
122         m_isDisparityReady = m_isStereoReady && OnCalculateDisparity();
123
124         return m_isDisparityReady;
125     }
126
127     virtual bool OnCalculateDisparityImage()
128     {
129         return false;
130     }
131     
132     virtual bool CalculateDisparityImage()
133     {
134         m_disparity_img = CreateIsometricImage( m_left_img,
135                                                 m_disparity_img,
136                                                 m_left_img -> depth,
137                                                 m_left_img -> nChannels
138                                               );
139         if( !m_isDisparityReady ) {
140             m_isDisparityReady = CalculateDisparity();
141         }
142         OnCalculateDisparityImage();
143
144         return true;
145     }
146
147     virtual void  SetImage( IplImage* src, IplImage*& dst,
148                             bool substitute_pointer = false )
149     {
150         if( dst != src )
151         {
152             if( substitute_pointer )
153             {
154                 cvReleaseImage( &dst );
155                 dst = src;
156             }
157             else
158             {
159                 dst = CreateIsometricImage( src, dst, src->depth, src->nChannels );
160                 cvCopy( src, dst );
161             }
162         }
163         ResetStereo();
164     }
165
166 public:
167
168     CCvMorpher()
169     {
170         Clear();
171     }
172
173     virtual ~CCvMorpher()
174     {
175         Release();
176     }
177
178     virtual void SetLeftImage( IplImage* img, bool substitute_pointer = false )
179     {
180         SetImage( img, m_left_img, substitute_pointer );
181     }
182
183     virtual void SetRightImage( IplImage* img, bool substitute_pointer = false )
184     {
185         SetImage( img, m_right_img, substitute_pointer );
186     }
187
188     virtual IplImage* GetLeftImage() { return m_left_img; }
189     virtual IplImage* GetRightImage() { return m_right_img; }
190
191     virtual IplImage* GetVirtualImage()
192     {
193         if( !m_isVirtualImageReady )
194         {
195             if( !m_isStereoReady )
196             {
197                 m_isStereoReady = CalculateStereo();
198             }
199             m_isVirtualImageReady = m_isStereoReady && CalculateVirtualImage();
200         }
201         return m_virtual_img;
202     }
203
204     virtual IplImage* GetDisparityImage()
205     {
206         if( !m_isStereoReady ) {
207             m_isStereoReady = CalculateStereo();
208         }
209         CalculateDisparityImage();
210
211         return m_disparity_img;
212     }
213
214     virtual void SetPan( float pan )
215     {
216         assert( 0.f <= pan && pan <= 1.f );
217         m_pan = pan;
218         
219         m_isVirtualImageReady = false;
220     }
221
222     float GetPan() { return m_pan; };
223 };
224
225
226 // Subdivision + LK - based viewmorphing
227 class CCvSubdivMorpher : public CCvMorpher
228 {
229 protected:
230
231     int  m_count;
232     int  m_realcount;
233     int  m_maxcount;
234     CvSubdiv2D* m_subdiv;
235     CvPoint2D32f* m_left_points;
236     CvPoint2D32f* m_right_points;
237     IplImage* m_left_gray_img;
238     IplImage* m_right_gray_img;
239     IplImage* m_left_pyr;
240     IplImage* m_right_pyr;
241     CvSize m_win_size;
242     int  m_pyr_level;
243     CvTermCriteria m_criteria;
244
245     void ClearPoints()
246     {
247         m_left_points = m_right_points = 0;
248         m_count = m_maxcount = 0;
249     }
250
251     virtual void ReleasePoints()
252     {
253         cvClearGraph( (CvGraph*)m_subdiv );
254         delete m_left_points;
255         delete m_right_points;
256         ClearPoints();
257     }
258
259     void Clear()
260     {
261         CCvMorpher::Clear();
262         ClearPoints();
263         m_left_gray_img = m_right_gray_img = 0;
264         m_left_pyr = m_right_pyr = 0;
265         m_realcount = 0;
266     }
267
268     virtual void Release()
269     {
270         CCvMorpher::Release();
271         ReleasePoints();
272         cvReleaseImage( &m_left_gray_img );
273         cvReleaseImage( &m_right_gray_img );
274         cvReleaseImage( &m_left_pyr );
275         cvReleaseImage( &m_right_pyr );
276         Clear();
277     }
278
279     virtual bool  OnCalculateStereo();
280     virtual bool  OnCalculateVirtualImage();
281     virtual bool  GeneratePoints();
282     virtual void  MorphFacet( CvSubdiv2DEdge edge );
283
284 public:
285
286     CCvSubdivMorpher();
287
288     int GetPointCount() { return m_count; }
289     void SetPointCount( int count )
290     {
291         if( count > m_maxcount )
292         {
293             ReleasePoints();
294             m_left_points = new CvPoint2D32f[count];
295             m_right_points = new CvPoint2D32f[count];
296             m_maxcount = count;
297         }
298         m_count = count;
299         ResetStereo();
300     }
301 };
302
303 // Pixel to pixel morphing
304 class CCvPixelToPixelMorpher : public CCvMorpher
305 {
306 protected:
307     int     m_maxPixelDifference;
308     int*    m_corr;
309     int*    m_corrNum;
310
311 protected:
312     struct _Color
313     {
314         unsigned char red;
315         unsigned char green;
316         unsigned char blue;
317     };
318     
319     typedef enum {
320         CORR_ARRAY      = 0,
321         NUM_CORR_ARRAY  = 1,
322         CORR_EDGES      = 2,
323         CORR_TEMP       = 3
324     } corrArrayType;
325     
326     typedef enum {
327         morphNormalImage    = 0,
328         morphDepthMap       = 1
329     } morphImageType;
330
331 protected:
332     int* corrAlloc( int width, int height, corrArrayType type, int maxPixelDifference = 0 );
333     void FindFullCorr( unsigned char* _leftImage,
334                        int _leftLineStep,
335                        unsigned char* _rightImage,
336                        int _rightLineStep,
337                        int* _corrArray,
338                        int* _numCorrArray,
339                        int width,
340                        int height,
341                        int maxPixelDifference
342                      );
343     void FindCorr( unsigned char* _leftLine,
344                    unsigned char* _rightLine,
345                    int* _corrArray,
346                    int* numCorrArray,
347                    int width,
348                    int* edges,
349                    int* tempArray
350                  );
351     
352     void Morph( unsigned char* _leftImage,
353                 int _leftLineStep,
354                 unsigned char* _rightImage,
355                 int _rightLineStep,
356                 unsigned char* _resultImage,
357                 int _resultLineStep,
358                 int* _corrArray,
359                 int* _numCorrArray,
360                 int width,
361                 int height,
362                 float alpha,
363                 morphImageType imageNeed    = morphNormalImage,
364                 int maxDifference           = 0
365               );
366     
367     int distance( unsigned char* _leftLine,
368                   unsigned char* _rightLine,
369                   int lineSize,
370                   int x,
371                   int y
372                 );
373
374     void Clear()
375     {
376         CCvMorpher::Clear();
377         m_maxPixelDifference = 10;
378         m_corr = m_corrNum = 0;
379     }
380
381     virtual void Release()
382     {
383         CCvMorpher::Release();
384         if( m_corr ) {
385             free( m_corr );
386         }
387         if( m_corrNum ) {
388             free( m_corrNum );
389         }
390         Clear();
391     }
392
393     virtual bool  OnCalculateStereo();
394     virtual bool  OnCalculateVirtualImage();
395     virtual bool  OnCalculateDisparity();
396     virtual bool  OnCalculateDisparityImage();
397
398 public:
399
400     CCvPixelToPixelMorpher();
401 };
402
403 /* End of file. */