Update to 2.0.0 tree from current Fremantle build
[opencv] / interfaces / swig / python / adaptors.py
1 #########################################################################################
2 #
3 #  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 #
5 #  By downloading, copying, installing or using the software you agree to this license.
6 #  If you do not agree to this license, do not download, install,
7 #  copy or use the software.
8 #
9 #
10 #                        Intel License Agreement
11 #                For Open Source Computer Vision Library
12 #
13 # Copyright (C) 2000, Intel Corporation, all rights reserved.
14 # Third party copyrights are property of their respective owners.
15 #
16 # Redistribution and use in source and binary forms, with or without modification,
17 # are permitted provided that the following conditions are met:
18 #
19 #   * Redistribution's of source code must retain the above copyright notice,
20 #     this list of conditions and the following disclaimer.
21 #
22 #   * Redistribution's in binary form must reproduce the above copyright notice,
23 #     this list of conditions and the following disclaimer in the documentation
24 #     and/or other materials provided with the distribution.
25 #
26 #   * The name of Intel Corporation may not be used to endorse or promote products
27 #     derived from this software without specific prior written permission.
28 #
29 # This software is provided by the copyright holders and contributors "as is" and
30 # any express or implied warranties, including, but not limited to, the implied
31 # warranties of merchantability and fitness for a particular purpose are disclaimed.
32 # In no event shall the Intel Corporation or contributors be liable for any direct,
33 # indirect, incidental, special, exemplary, or consequential damages
34 # (including, but not limited to, procurement of substitute goods or services;
35 # loss of use, data, or profits; or business interruption) however caused
36 # and on any theory of liability, whether in contract, strict liability,
37 # or tort (including negligence or otherwise) arising in any way out of
38 # the use of this software, even if advised of the possibility of such damage.
39 #
40 #########################################################################################
41
42
43 # 2004-03-16, Mark Asbach <asbach@ient.rwth-aachen.de>
44 #             Institute of Communications Engineering, RWTH Aachen University
45 # 2007-02-xx, direct interface to numpy by Vicent Mas <vmas@carabos.com>
46 #             Carabos Coop. V.
47 # 2007-10-08, try/catch 
48
49 """Adaptors to interchange data with numpy and/or PIL
50
51 This module provides explicit conversion of OpenCV images/matrices to and from
52 the Python Imaging Library (PIL) and python's newest numeric library (numpy).
53
54 Currently supported image/matrix formats are:
55     - 3 x  8 bit  RGB (GBR)
56     - 1 x  8 bit  Grayscale
57     - 1 x 32 bit  Float
58
59 In numpy, images are represented as multidimensional arrays with
60 a third dimension representing the image channels if more than one
61 channel is present.
62 """
63
64 import cv
65
66 try:
67   import PIL.Image
68
69   ###########################################################################
70   def Ipl2PIL(input):
71       """Converts an OpenCV/IPL image to PIL the Python Imaging Library.
72   
73       Supported input image formats are
74          IPL_DEPTH_8U  x 1 channel
75          IPL_DEPTH_8U  x 3 channels
76          IPL_DEPTH_32F x 1 channel
77       """
78   
79       if not isinstance(input, cv.CvMat):
80           raise TypeError, 'must be called with a cv.CvMat!'
81     
82       #orientation
83       if input.origin == 0:
84           orientation = 1 # top left
85       elif input.origin == 1:
86           orientation = -1 # bottom left
87       else:
88           raise ValueError, 'origin must be 0 or 1!'
89   
90       # mode dictionary:
91       # (channels, depth) : (source mode, dest mode, depth in byte)
92       mode_list = {
93           (1, cv.IPL_DEPTH_8U)  : ("L", "L", 1),
94           (3, cv.IPL_DEPTH_8U)  : ("BGR", "RGB", 3),
95           (1, cv.IPL_DEPTH_32F) : ("F", "F", 4)
96           }
97   
98       key = (input.nChannels, input.depth)
99       if not mode_list.has_key(key):
100           raise ValueError, 'unknown or unsupported input mode'
101   
102       modes = mode_list[key]
103   
104       return PIL.Image.fromstring(
105           modes[1], # mode
106           (input.width, input.height), # size tuple
107           input.imageData, # data
108           "raw",
109           modes[0], # raw mode
110           input.widthStep, # stride
111           orientation # orientation
112           )
113   
114   
115   ###########################################################################
116   def PIL2Ipl(input):
117       """Converts a PIL image to the OpenCV/IPL CvMat data format.
118   
119       Supported input image formats are:
120           RGB
121           L
122           F
123       """
124   
125       if not (isinstance(input, PIL.Image.Image)):
126           raise TypeError, 'Must be called with PIL.Image.Image!'
127       
128       # mode dictionary:
129       # (pil_mode : (ipl_depth, ipl_channels)
130       mode_list = {
131           "RGB" : (cv.IPL_DEPTH_8U, 3),
132           "L"   : (cv.IPL_DEPTH_8U, 1),
133           "F"   : (cv.IPL_DEPTH_32F, 1)
134           }
135       
136       if not mode_list.has_key(input.mode):
137           raise ValueError, 'unknown or unsupported input mode'
138       
139       result = cv.cvCreateImage(
140           cv.cvSize(input.size[0], input.size[1]),  # size
141           mode_list[input.mode][0],  # depth
142           mode_list[input.mode][1]  # channels
143           )
144   
145       # set imageData
146       result.imageData = input.tostring()
147       return result
148
149 except ImportError:
150   pass
151
152
153 #############################################################################
154 #############################################################################
155
156 try:
157   
158   import numpy
159   
160   
161   ###########################################################################
162   def NumPy2Ipl(input):
163       """Converts a numpy array to the OpenCV/IPL CvMat data format.
164   
165       Supported input array layouts:
166          2 dimensions of numpy.uint8
167          3 dimensions of numpy.uint8
168          2 dimensions of numpy.float32
169          2 dimensions of numpy.float64
170       """
171       
172       if not isinstance(input, numpy.ndarray):
173           raise TypeError, 'Must be called with numpy.ndarray!'
174   
175       # Check the number of dimensions of the input array
176       ndim = input.ndim
177       if not ndim in (2, 3):
178           raise ValueError, 'Only 2D-arrays and 3D-arrays are supported!'
179       
180       # Get the number of channels
181       if ndim == 2:
182           channels = 1
183       else:
184           channels = input.shape[2]
185       
186       # Get the image depth
187       if input.dtype == numpy.uint8:
188           depth = cv.IPL_DEPTH_8U
189       elif input.dtype == numpy.float32:
190           depth = cv.IPL_DEPTH_32F
191       elif input.dtype == numpy.float64:
192           depth = cv.IPL_DEPTH_64F
193       
194       # supported modes list: [(channels, dtype), ...]
195       modes_list = [(1, numpy.uint8), (3, numpy.uint8), (1, numpy.float32), (1, numpy.float64)]
196       
197       # Check if the input array layout is supported
198       if not (channels, input.dtype) in modes_list:
199           raise ValueError, 'Unknown or unsupported input mode'
200       
201       result = cv.cvCreateImage(
202           cv.cvSize(input.shape[1], input.shape[0]),  # size
203           depth,  # depth
204           channels  # channels
205           )
206       
207       # set imageData
208       result.imageData = input.tostring()
209       
210       return result
211   
212   
213   ###########################################################################
214   def Ipl2NumPy(input):
215       """Converts an OpenCV/IPL image to a numpy array.
216   
217       Supported input image formats are
218          IPL_DEPTH_8U  x 1 channel
219          IPL_DEPTH_8U  x 3 channels
220          IPL_DEPTH_32F x 1 channel
221          IPL_DEPTH_32F x 2 channels
222          IPL_DEPTH_32S x 1 channel
223          IPL_DEPTH_64F x 1 channel
224          IPL_DEPTH_64F x 2 channels
225       """
226       
227       if not isinstance(input, cv.CvMat):
228           raise TypeError, 'must be called with a cv.CvMat!'
229             
230       # data type dictionary:
231       # (channels, depth) : numpy dtype
232       ipl2dtype = {
233           (1, cv.IPL_DEPTH_8U)  : numpy.uint8,
234           (3, cv.IPL_DEPTH_8U)  : numpy.uint8,
235           (1, cv.IPL_DEPTH_32F) : numpy.float32,
236           (2, cv.IPL_DEPTH_32F) : numpy.float32,
237           (1, cv.IPL_DEPTH_32S) : numpy.int32,
238           (1, cv.IPL_DEPTH_64F) : numpy.float64,
239           (2, cv.IPL_DEPTH_64F) : numpy.float64
240           }
241       
242       key = (input.nChannels, input.depth)
243       if not ipl2dtype.has_key(key):
244           raise ValueError, 'unknown or unsupported input mode'
245       
246       # Get the numpy array and reshape it correctly
247       # ATTENTION: flipped dimensions width/height on 2007-11-15
248       if input.nChannels == 1:
249           array_1d = numpy.fromstring(input.imageData, dtype=ipl2dtype[key])
250           return numpy.reshape(array_1d, (input.height, input.width))
251       elif input.nChannels == 2:
252           array_1d = numpy.fromstring(input.imageData, dtype=ipl2dtype[key])
253           return numpy.reshape(array_1d, (input.height, input.width, 2))
254       elif input.nChannels == 3:
255           # Change the order of channels from BGR to RGB
256           rgb = cv.cvCreateImage(cv.cvSize(input.width, input.height), input.depth, 3)
257           cv.cvCvtColor(input, rgb, cv.CV_BGR2RGB)
258           array_1d = numpy.fromstring(rgb.imageData, dtype=ipl2dtype[key])
259           return numpy.reshape(array_1d, (input.height, input.width, 3))
260
261 except ImportError:
262   pass
263
264
265 ###########################################################################
266 ###########################################################################
267
268
269 try:
270
271   import PIL.Image
272   import numpy
273
274   ###########################################################################
275   def PIL2NumPy(input):
276       """THIS METHOD IS DEPRECATED
277       
278       Converts a PIL image to a numpy array.
279   
280       Supported input image formats are:
281           RGB
282           L
283           F
284       """
285   
286       if not (isinstance(input, PIL.Image.Image)):
287           raise TypeError, 'Must be called with PIL.Image.Image!'
288   
289       # modes dictionary:
290       # pil_mode : numpy dtype
291       modes_map = {
292           "RGB" : numpy.uint8,
293           "L"   : numpy.uint8,
294           "F"   : numpy.float32
295           }
296   
297       if not modes_map.has_key(input.mode):
298           raise ValueError, 'Unknown or unsupported input mode!. Supported modes are RGB, L and F.'
299   
300       result_ro = numpy.asarray(input, dtype=modes_map[input.mode])  # Read-only array
301       return result_ro.copy()  # Return a writeable array
302   
303   
304   ###########################################################################
305   def NumPy2PIL(input):
306       """THIS METHOD IS DEPRECATED
307       
308       Converts a numpy array to a PIL image.
309   
310       Supported input array layouts:
311          2 dimensions of numpy.uint8
312          3 dimensions of numpy.uint8
313          2 dimensions of numpy.float32
314       """
315   
316       if not isinstance(input, numpy.ndarray):
317           raise TypeError, 'Must be called with numpy.ndarray!'
318   
319       # Check the number of dimensions of the input array
320       ndim = input.ndim
321       if not ndim in (2, 3):
322           raise ValueError, 'Only 2D-arrays and 3D-arrays are supported!'
323   
324       if ndim == 2:
325           channels = 1
326       else:
327           channels = input.shape[2]
328   
329       # supported modes list: [(channels, dtype), ...]
330       modes_list = [(1, numpy.uint8), (3, numpy.uint8), (1, numpy.float32)]
331   
332       mode = (channels, input.dtype)
333       if not mode in modes_list:
334           raise ValueError, 'Unknown or unsupported input mode'
335   
336       return PIL.Image.fromarray(input)
337
338 except ImportError:
339   pass