00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <pcl/pcl_config.h>
00039 #ifdef HAVE_OPENNI
00040
00041 #include <pcl/io/openni_camera/openni_image_bayer_grbg.h>
00042 #include <sstream>
00043 #include <iostream>
00044 #include <pcl/io/debayer.h>
00045
00046 #define AVG(a,b) static_cast<unsigned char>((int(a) + int(b)) >> 1)
00047 #define AVG3(a,b,c) static_cast<unsigned char>((int(a) + int(b) + int(c)) / 3)
00048 #define AVG4(a,b,c,d) static_cast<unsigned char>((int(a) + int(b) + int(c) + int(d)) >> 2)
00049 #define WAVG4(a,b,c,d,x,y) static_cast<unsigned char>( ( (int(a) + int(b)) * int(x) + (int(c) + int(d)) * int(y) ) / ( (int(x) + (int(y))) << 1 ) )
00050 using namespace std;
00051
00053 openni_wrapper::ImageBayerGRBG::ImageBayerGRBG (boost::shared_ptr<xn::ImageMetaData> image_meta_data, DebayeringMethod method) throw ()
00054 : Image (image_meta_data)
00055 , debayering_method_ (method)
00056 {
00057 }
00058
00060 openni_wrapper::ImageBayerGRBG::~ImageBayerGRBG () throw ()
00061 {
00062 }
00063
00065 bool
00066 openni_wrapper::ImageBayerGRBG::isResizingSupported (
00067 unsigned input_width, unsigned input_height,
00068 unsigned output_width, unsigned output_height) const
00069 {
00070 return (openni_wrapper::ImageBayerGRBG::resizingSupported (input_width, input_height, output_width, output_height));
00071 }
00072
00074 void
00075 openni_wrapper::ImageBayerGRBG::fillGrayscale (
00076 unsigned width, unsigned height,
00077 unsigned char* gray_buffer, unsigned gray_line_step) const
00078 {
00079 if (width > image_md_->XRes () || height > image_md_->YRes ())
00080 THROW_OPENNI_EXCEPTION ("Upsampling not supported. Request was: %d x %d -> %d x %d", image_md_->XRes (), image_md_->YRes (), width, height);
00081
00082 if (gray_line_step == 0)
00083 gray_line_step = width;
00084
00085
00086 unsigned gray_line_skip = gray_line_step - width;
00087 if (image_md_->XRes () == width && image_md_->YRes () == height)
00088 {
00089 const XnUInt8 *bayer_pixel = image_md_->Data ();
00090 int line_skip = image_md_->XRes ();
00091 if (debayering_method_ == Bilinear)
00092 {
00093
00094 for (register unsigned xIdx = 0; xIdx < width - 2; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00095 {
00096 gray_buffer[0] = bayer_pixel[0];
00097 gray_buffer[1] = AVG3 (bayer_pixel[0], bayer_pixel[2], bayer_pixel[1 + line_skip]);
00098 }
00099 gray_buffer[0] = bayer_pixel[0];
00100 gray_buffer[1] = AVG (bayer_pixel[0], bayer_pixel[1 + line_skip]);
00101 gray_buffer += 2 + gray_line_skip;
00102 bayer_pixel += 2;
00103
00104 for (register unsigned yIdx = 1; yIdx < height - 1; yIdx += 2)
00105 {
00106
00107 gray_buffer[0] = AVG3 (bayer_pixel[-line_skip], bayer_pixel[line_skip], bayer_pixel[1]);
00108 gray_buffer[1] = bayer_pixel[1];
00109 gray_buffer += 2;
00110 bayer_pixel += 2;
00111 for (register unsigned xIdx = 2; xIdx < width; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00112 {
00113 gray_buffer[0] = AVG4 (bayer_pixel[-line_skip], bayer_pixel[line_skip], bayer_pixel[-1], bayer_pixel[1]);
00114 gray_buffer[1] = bayer_pixel[1];
00115 }
00116 gray_buffer += gray_line_skip;
00117
00118
00119 for (register unsigned xIdx = 0; xIdx < width - 2; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00120 {
00121 gray_buffer[0] = bayer_pixel[0];
00122 gray_buffer[1] = AVG4 (bayer_pixel[0], bayer_pixel[2], bayer_pixel[-line_skip + 1], bayer_pixel[line_skip + 1]);
00123 }
00124 gray_buffer[0] = bayer_pixel[0];
00125 gray_buffer[1] = AVG3 (bayer_pixel[-line_skip + 1], bayer_pixel[line_skip + 1], bayer_pixel[-1]);
00126 gray_buffer += 2 + gray_line_skip;
00127 bayer_pixel += 2;
00128 }
00129
00130
00131 gray_buffer[0] = AVG (bayer_pixel[1], bayer_pixel[-line_skip]);
00132 gray_buffer[1] = bayer_pixel[1];
00133 gray_buffer += 2;
00134 bayer_pixel += 2;
00135 for (register unsigned xIdx = 2; xIdx < width; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00136 {
00137 gray_buffer[0] = AVG3 (bayer_pixel[-1], bayer_pixel[1], bayer_pixel[-line_skip]);
00138 gray_buffer[1] = bayer_pixel[1];
00139 }
00140 }
00141 else if (debayering_method_ == EdgeAware)
00142 {
00143 int dv, dh;
00144
00145 for (register unsigned xIdx = 0; xIdx < width - 2; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00146 {
00147 gray_buffer[0] = bayer_pixel[0];
00148 gray_buffer[1] = AVG3 (bayer_pixel[0], bayer_pixel[2], bayer_pixel[1 + line_skip]);
00149 }
00150 gray_buffer[0] = bayer_pixel[0];
00151 gray_buffer[1] = AVG (bayer_pixel[0], bayer_pixel[1 + line_skip]);
00152 gray_buffer += 2 + gray_line_skip;
00153 bayer_pixel += 2;
00154
00155 for (register unsigned yIdx = 1; yIdx < height - 1; yIdx += 2)
00156 {
00157
00158 gray_buffer[0] = AVG3 (bayer_pixel[-line_skip], bayer_pixel[line_skip], bayer_pixel[1]);
00159 gray_buffer[1] = bayer_pixel[1];
00160 gray_buffer += 2;
00161 bayer_pixel += 2;
00162 for (register unsigned xIdx = 2; xIdx < width; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00163 {
00164 dv = abs (bayer_pixel[-line_skip] - bayer_pixel[line_skip]);
00165 dh = abs (bayer_pixel[-1] - bayer_pixel[1]);
00166 if (dh > dv)
00167 gray_buffer[0] = AVG (bayer_pixel[-line_skip], bayer_pixel[line_skip]);
00168 else if (dv > dh)
00169 gray_buffer[0] = AVG (bayer_pixel[-1], bayer_pixel[1]);
00170 else
00171 gray_buffer[0] = AVG4 (bayer_pixel[-line_skip], bayer_pixel[line_skip], bayer_pixel[-1], bayer_pixel[1]);
00172
00173 gray_buffer[1] = bayer_pixel[1];
00174 }
00175 gray_buffer += gray_line_skip;
00176
00177
00178 for (register unsigned xIdx = 0; xIdx < width - 2; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00179 {
00180 gray_buffer[0] = bayer_pixel[0];
00181
00182 dv = abs (bayer_pixel[1 - line_skip] - bayer_pixel[1 + line_skip]);
00183 dh = abs (bayer_pixel[0] - bayer_pixel[2]);
00184 if (dh > dv)
00185 gray_buffer[1] = AVG (bayer_pixel[1 - line_skip], bayer_pixel[1 + line_skip]);
00186 else if (dv > dh)
00187 gray_buffer[1] = AVG (bayer_pixel[0], bayer_pixel[2]);
00188 else
00189 gray_buffer[1] = AVG4 (bayer_pixel[0], bayer_pixel[2], bayer_pixel[-line_skip + 1], bayer_pixel[line_skip + 1]);
00190 }
00191 gray_buffer[0] = bayer_pixel[0];
00192 gray_buffer[1] = AVG3 (bayer_pixel[-line_skip + 1], bayer_pixel[line_skip + 1], bayer_pixel[-1]);
00193 gray_buffer += 2 + gray_line_skip;
00194 bayer_pixel += 2;
00195 }
00196
00197
00198 gray_buffer[0] = AVG (bayer_pixel[1], bayer_pixel[-line_skip]);
00199 gray_buffer[1] = bayer_pixel[1];
00200 gray_buffer += 2;
00201 bayer_pixel += 2;
00202 for (register unsigned xIdx = 2; xIdx < width; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00203 {
00204 gray_buffer[0] = AVG3 (bayer_pixel[-1], bayer_pixel[1], bayer_pixel[-line_skip]);
00205 gray_buffer[1] = bayer_pixel[1];
00206 }
00207 }
00208 else if (debayering_method_ == EdgeAwareWeighted)
00209 {
00210 int dv, dh;
00211
00212 for (register unsigned xIdx = 0; xIdx < width - 2; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00213 {
00214 gray_buffer[0] = bayer_pixel[0];
00215 gray_buffer[1] = AVG3 (bayer_pixel[0], bayer_pixel[2], bayer_pixel[1 + line_skip]);
00216 }
00217 gray_buffer[0] = bayer_pixel[0];
00218 gray_buffer[1] = AVG (bayer_pixel[0], bayer_pixel[1 + line_skip]);
00219 gray_buffer += 2 + gray_line_skip;
00220 bayer_pixel += 2;
00221
00222 for (register unsigned yIdx = 1; yIdx < height - 1; yIdx += 2)
00223 {
00224
00225 gray_buffer[0] = AVG3 (bayer_pixel[-line_skip], bayer_pixel[line_skip], bayer_pixel[1]);
00226 gray_buffer[1] = bayer_pixel[1];
00227 gray_buffer += 2;
00228 bayer_pixel += 2;
00229 for (register unsigned xIdx = 2; xIdx < width; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00230 {
00231 dv = abs (bayer_pixel[-line_skip] - bayer_pixel[line_skip]);
00232 dh = abs (bayer_pixel[-1] - bayer_pixel[1]);
00233
00234 if (dv == 0 && dh == 0)
00235 gray_buffer[0] = AVG4 (bayer_pixel[-line_skip], bayer_pixel[line_skip], bayer_pixel[-1], bayer_pixel[1]);
00236 else
00237 gray_buffer[0] = WAVG4 (bayer_pixel[-line_skip], bayer_pixel[line_skip], bayer_pixel[-1], bayer_pixel[1], dh, dv);
00238
00239 gray_buffer[1] = bayer_pixel[1];
00240 }
00241
00242 gray_buffer += gray_line_skip;
00243
00244
00245 for (register unsigned xIdx = 0; xIdx < width - 2; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00246 {
00247 gray_buffer[0] = bayer_pixel[0];
00248
00249 dv = abs (bayer_pixel[1 - line_skip] - bayer_pixel[1 + line_skip]);
00250 dh = abs (bayer_pixel[0] - bayer_pixel[2]);
00251
00252 if (dv == 0 && dh == 0)
00253 gray_buffer[1] = AVG4 (bayer_pixel[1 - line_skip], bayer_pixel[1 + line_skip], bayer_pixel[0], bayer_pixel[2]);
00254 else
00255 gray_buffer[1] = WAVG4 (bayer_pixel[1 - line_skip], bayer_pixel[1 + line_skip], bayer_pixel[0], bayer_pixel[2], dh, dv);
00256 }
00257 gray_buffer[0] = bayer_pixel[0];
00258 gray_buffer[1] = AVG3 (bayer_pixel[-line_skip + 1], bayer_pixel[line_skip + 1], bayer_pixel[-1]);
00259 gray_buffer += 2 + gray_line_skip;
00260 bayer_pixel += 2;
00261 }
00262
00263
00264 gray_buffer[0] = AVG (bayer_pixel[1], bayer_pixel[-line_skip]);
00265 gray_buffer[1] = bayer_pixel[1];
00266 gray_buffer += 2;
00267 bayer_pixel += 2;
00268 for (register unsigned xIdx = 2; xIdx < width; xIdx += 2, gray_buffer += 2, bayer_pixel += 2)
00269 {
00270 gray_buffer[0] = AVG3 (bayer_pixel[-1], bayer_pixel[1], bayer_pixel[-line_skip]);
00271 gray_buffer[1] = bayer_pixel[1];
00272 }
00273 }
00274 else
00275 THROW_OPENNI_EXCEPTION ("Unknown Debayering method: %d", debayering_method_);
00276
00277 }
00278 else
00279 {
00280 if ((image_md_->XRes () >> 1) % width != 0 || (image_md_->YRes () >> 1) % height != 0)
00281 THROW_OPENNI_EXCEPTION ("Downsampling only possible for multiple of 2 in both dimensions. Request was %d x %d -> %d x %d.", image_md_->XRes (), image_md_->YRes (), width, height);
00282
00283
00284 register unsigned bayerXStep = image_md_->XRes () / width;
00285 register unsigned bayerYSkip = (image_md_->YRes () / height - 1) * image_md_->XRes ();
00286
00287
00288 register const XnUInt8* bayer_buffer = image_md_->Data ();
00289
00290 for (register unsigned yIdx = 0; yIdx < height; ++yIdx, bayer_buffer += bayerYSkip, gray_buffer += gray_line_skip)
00291 {
00292 for (register unsigned xIdx = 0; xIdx < width; ++xIdx, ++gray_buffer, bayer_buffer += bayerXStep)
00293 {
00294 *gray_buffer = AVG (bayer_buffer[0], bayer_buffer[ image_md_->XRes () + 1]);
00295 }
00296 }
00297 }
00298 }
00299
00301 void
00302 openni_wrapper::ImageBayerGRBG::fillRGB (
00303 unsigned width, unsigned height,
00304 unsigned char* rgb_buffer, unsigned rgb_line_step) const
00305 {
00306 if (width > image_md_->XRes () || height > image_md_->YRes ())
00307 THROW_OPENNI_EXCEPTION ("Upsampling only possible for multiple of 2 in both dimensions. Request was %d x %d -> %d x %d.", image_md_->XRes (), image_md_->YRes (), width, height);
00308
00309 if (rgb_line_step == 0)
00310 rgb_line_step = width * 3;
00311
00312
00313 unsigned rgb_line_skip = rgb_line_step - width * 3;
00314
00315 if (image_md_->XRes () == width && image_md_->YRes () == height)
00316 {
00317 register const unsigned char* bayer_pixel = image_md_->Data ();
00318
00319 int bayer_line_step = image_md_->XRes ();
00320 int bayer_line_step2 = image_md_->XRes () << 1;
00321
00322 pcl::io::DeBayer d;
00323 if (debayering_method_ == Bilinear)
00324 d.debayerBilinear (bayer_pixel, rgb_buffer, width, height, bayer_line_step, bayer_line_step2, rgb_line_step);
00325 else if (debayering_method_ == EdgeAware)
00326 d.debayerEdgeAware (bayer_pixel, rgb_buffer, width, height, bayer_line_step, bayer_line_step2, rgb_line_step);
00327 else if (debayering_method_ == EdgeAwareWeighted)
00328 d.debayerEdgeAwareWeighted (bayer_pixel, rgb_buffer, width, height, bayer_line_step, bayer_line_step2, rgb_line_step);
00329 else
00330 THROW_OPENNI_EXCEPTION ("Unknown debayering method: %d", debayering_method_);
00331 }
00332 else
00333 {
00334 if (image_md_->XRes () % width != 0 || image_md_->YRes () % height != 0)
00335 THROW_OPENNI_EXCEPTION ("Downsampling only possible for integer scales in both dimensions. Request was %d x %d -> %d x %d.", image_md_->XRes (), image_md_->YRes (), width, height);
00336
00337
00338 register unsigned bayerXStep = image_md_->XRes () / width;
00339 register unsigned bayerYSkip = (image_md_->YRes () / height - 1) * image_md_->XRes ();
00340
00341
00342 register const XnUInt8* bayer_buffer = image_md_->Data ();
00343
00344 for (register unsigned yIdx = 0; yIdx < height; ++yIdx, bayer_buffer += bayerYSkip, rgb_buffer += rgb_line_skip)
00345 {
00346 for (register unsigned xIdx = 0; xIdx < width; ++xIdx, rgb_buffer += 3, bayer_buffer += bayerXStep)
00347 {
00348 rgb_buffer[ 2 ] = bayer_buffer[ image_md_->XRes () ];
00349 rgb_buffer[ 1 ] = AVG (bayer_buffer[0], bayer_buffer[ image_md_->XRes () + 1]);
00350 rgb_buffer[ 0 ] = bayer_buffer[ 1 ];
00351 }
00352 }
00353 }
00354 }
00355
00356 #endif