30 #include <vigra/imageinfo.hxx>
31 #include <vigra/transformimage.hxx>
32 #include <vigra/colorconversions.hxx>
35 #include <vigra/resizeimage.hxx>
38 #include <vigra/rgbvalue.hxx>
43 #define PI 3.14159265358979323846
50 #define snprintf _snprintf
58 template <
class PixelType>
67 template <
class PixelType>
76 template <
class PixelType>
89 typedef typename vigra::NumericTraits<PixelType>::isScalar
srcIsScalar;
138 template <
class PixelType>
139 Khan<PixelType>::Khan(std::vector<std::string>& newInputFiles,
const uint16_t newFlags,
const uint16_t newDebugFlags,
140 int newIterations,
double newSigma,
int newVerbosity) {
150 const char * fileType= vigra::ImageImportInfo(newInputFiles[0].c_str()).getFileType();
151 if ( (!strcmp(fileType,
"TIFF") && strcmp(fileType,
"UINT8")) || !strcmp(fileType,
"EXR") || !strcmp(fileType,
"FLOAT")) {
152 setSigma(newSigma/10);
157 for (
unsigned int i=0; i<5; i++)
166 template <
class PixelType>
171 template <
class PixelType>
175 return std::atan(-(x*x)+
sigma)/
PI + 0.5;
178 return (std::exp(-(x*x)/(2*
sigma*
sigma)) * denom);
211 template <
class PixelType>
213 vigra::RGB2LabFunctor<float> RGB2Lab;
218 template <
class PixelType>
224 template <
class PixelType>
227 vigra::RGBToGrayAccessor<vigra::FRGBImage::PixelType> color2gray;
228 vigra::FRGBImage tmpImg(getOutputROI().size());
229 vigra::Point2D offset = vigra::Point2D(info.getPosition());
230 offset -= getOutputROI().upperLeft();
231 if (info.numBands() == 4) {
232 vigra::BImage imgAlpha(tmpImg.size());
235 vigra::importImage(info,
destImage(tmpImg, offset));
241 template <
class PixelType>
243 vigra::Point2D offset = vigra::Point2D(info.getPosition());
244 offset -= getOutputROI().upperLeft();
245 if (info.numBands() == 4) {
246 vigra::BImage imgAlpha(img->size());
249 vigra::importImage(info,
destImage(*img, offset));
253 template <
class PixelType>
255 vigra::ImageImportInfo imgInfo(inputFiles[i]);
257 weight =
FImagePtr(
new vigra::FImage(getOutputROI().size()));
263 if (imgInfo.isColor()) {
266 importImage(imgInfo,
destImage(*pInputImg));
275 const char * fileType= imgInfo.getFileType();
276 if ( (!strcmp(fileType,
"TIFF") && strcmp(fileType,
"UINT8")) || !strcmp(fileType,
"EXR") || !strcmp(fileType,
"FLOAT")) {
282 vigra::FindMinMax<float> minmax;
300 template <
class PixelType>
302 for (
unsigned int i = 0; i < inputFiles.size(); i++) {
305 preprocessImage(i, weight, processImage);
306 processImages.push_back(processImage);
307 weights.push_back(weight);
312 snprintf(tmpfn, 99,
"init_weights_%u.tiff", i);
313 vigra::ImageExportInfo exWeights(tmpfn);
320 const int origWidth = weights[0]->width();
321 const int origHeight = weights[0]->height();
324 std::vector<ProcessImageTypePtr> backupLab;
326 for (
unsigned int i = 0; i < processImages.size(); i++) {
328 backupLab.push_back(processImages[i]);
333 std::cout <<
"Running khan algorithm" << std::endl;
338 std::cout <<
"iteration " << it+1 << std::endl;
341 std::cout <<
"copying weights from previous iteration" << std::endl;
343 std::vector<FImagePtr> prevWeights;
344 for (
unsigned int i = 0; i < weights.size(); i++) {
346 if (
flags & ADV_MULTIRES) {
351 int resized_width = origWidth / ( iterations/(it+1) );
353 int resized_height = origHeight / ( iterations/(it+1) );
355 vigra::FImage resizedWeight;
358 if (resized_width > 100 && resized_height > 100) {
360 resizedWeight = vigra::FImage(vigra::Size2D(resized_width,resized_height));
361 resizedLab =
ProcessImageType(vigra::Size2D(resized_width, resized_height));
362 }
else if (origWidth >= 100 && origHeight >= 100) {
364 if (origWidth >= origHeight) {
365 resizedWeight = vigra::FImage(vigra::Size2D(100 * origWidth / origHeight, 100));
366 resizedLab =
ProcessImageType(vigra::Size2D(100 * origWidth / origHeight, 100));
368 resizedWeight = vigra::FImage(vigra::Size2D(100, 100 * origHeight / origWidth));
369 resizedLab =
ProcessImageType(vigra::Size2D(100, 100 * origHeight / origWidth));
381 FImagePtr tmp(
new vigra::FImage(resizedWeight));
382 prevWeights.push_back(tmp);
384 weights[i] =
FImagePtr(
new vigra::FImage(resizedWeight));
387 FImagePtr tmp(
new vigra::FImage(*weights[i]));
388 prevWeights.push_back(tmp);
393 for (
unsigned int i = 0; i < processImages.size(); i++) {
395 std::cout <<
"processing image " << i+1 << std::endl;
401 double wpqsKhsum = 0;
403 const int width = processImages[i]->width();
404 const int height = processImages[i]->height();
411 vigra::FImage::traverser wy = weights[i]->upperLeft();
413 for (
int y=0; sy.y != send.y; ++sy.y, ++wy.y, ++y) {
417 vigra::FImage::traverser wx = wy;
419 for (
int x=0; sx.x != send.x; ++sx.x, ++wx.x, ++x) {
421 std::cout <<
"processing pixel (" << x+1 <<
"," << y+1 <<
")" << std::endl;
426 for (
unsigned int j = 0; j < processImages.size(); j++) {
428 std::cout <<
"processing layer " << j << std::endl;
433 vigra::FImage::traverser weighty = prevWeights[j]->upperLeft();
448 for (; ndy <= maxDisty; ++neighby.y, ++weighty.y, ++ndy) {
450 vigra::FImage::traverser weightx = weighty;
464 for (; ndx <= maxDistx; ++neighbx.x, ++weightx.x, ++ndx) {
466 std::cout <<
"(" << ndx <<
"," << ndy <<
")";
469 if (ndx != 0 || ndy != 0) {
470 wpqsKhsum += (*weightx * Kh(X-(*neighbx)));
477 std::cout << std::endl;
484 std::cout <<
"computing new weight" << std::endl;
490 *wx = (float)wpqsKhsum / wpqssum;
492 *wx *= (float)wpqsKhsum / wpqssum;
496 wpqsKhsum = wpqssum = 0;
504 std::cout <<
"normalizing weights" << std::endl;
505 double factor = 255.0f/maxWeight;
506 for (
unsigned int i=0; i<weights.size(); ++i) {
const uint16_t ADV_MULTIRES
std::vector< ProcessImageTypePtr > processImages
ImageTypes< PixelType >::ProcessImageType::PixelType ProcessImagePixelType
ImageTypes< PixelType >::ProcessImageTypePtr ProcessImageTypePtr
void transformImage(vigra::triple< SrcImageIterator, SrcImageIterator, SrcAccessor > src, vigra::triple< DestImageIterator, DestImageIterator, DestAccessor > dest, std::pair< AlphaImageIterator, AlphaAccessor > alpha, vigra::Diff2D destUL, TRANSFORM &transform, PixelTransform &pixelTransform, bool warparound, Interpolator interpol, AppBase::ProgressDisplay *progress, bool singleThreaded=false)
Transform an image into the panorama.
virtual void setVerbosity(int verbosity)
set verbosity level
ImageTypes< PixelType >::ProcessImageType::traverser ProcessImageTraverser
virtual void setDebugFlags(const uint16_t debugFlags)
set flags for debugging purposes
void convertImage(ImageType *in, ProcessImageTypePtr &out, vigra::VigraFalseType)
convert image for internal use if input image is RGB then convert it to L*a*b if input image is grays...
virtual void loadImages(std::vector< std::string > &inputFiles)
load images for processing
vigra::BasicImage< float > ProcessImageType
std::shared_ptr< ImageType > ImagePtr
#define PI
Header file for Khan's deghosting algorithm Copyright (C) 2009 Lukáš Jirkovský l...
virtual void setFlags(const uint16_t flags)
set advanced flags Allows to change behavior of used algorithm
ImageTypes< PixelType >::ImageType ImageType
virtual std::vector< FImagePtr > createWeightMasks() override
create weight masks create weight masks for masking out ghosting regions
std::shared_ptr< ProcessImageType > ProcessImageTypePtr
std::shared_ptr< vigra::FImage > FImagePtr
vigra::FRGBImage ImageType
std::shared_ptr< ProcessImageType > ProcessImageTypePtr
Fuctor to normalize values.
virtual void setIterationNum(const int iterations)
set number of iterations
vigra::pair< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImage(ROIImage< Image, Alpha > &img)
vigra::triple< typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::image_const_traverser, typename ROIImage< Image, Mask >::ImageConstAccessor > srcImageRange(const ROIImage< Image, Mask > &img)
helper function for ROIImages
const uint16_t SAVE_INITWEIGHTS
vigra::NumericTraits< PixelType >::isScalar srcIsScalar
void importImageAlpha(const ImageImportInfo &import_info, ImageIterator image_iterator, ImageAccessor image_accessor, AlphaIterator alpha_iterator, AlphaAccessor alpha_accessor)
Read the image specified by the given vigra::ImageImportInfo object including its alpha channel...
vigra::RGBValue< T, RIDX, GIDX, BIDX > log(vigra::RGBValue< T, RIDX, GIDX, BIDX > const &v)
component-wise logarithm
void importRGBImage(vigra::ImageImportInfo &info, ImageType *img, vigra::VigraFalseType)
import RGB image
Functor to apply mexican hat function returns very small values for input near to 0 or 255...
static uint16_t debugFlags
float Kh(ProcessImagePixelType x)
transform image using EMoR response
void setSigma(double sigma)
set sigma sets sigma for gaussian weigting function
std::shared_ptr< ImageType > ImagePtr
vigra::triple< typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::image_traverser, typename ROIImage< Image, Alpha >::ImageAccessor > destImageRange(ROIImage< Image, Alpha > &img)
Khan(std::vector< std::string > &inputFiles, const uint16_t flags, const uint16_t debugFlags, int iterations, double sigma, int verbosity)
void copyImage(SrcImageIterator src_upperleft, SrcImageIterator src_lowerright, SrcAccessor src_acc, DestImageIterator dest_upperleft, DestAccessor dest_acc)
static void info(const char *fmt,...)
vigra::BasicImage< vigra::AlgTinyVector< float, 3 > > ProcessImageType
std::vector< FImagePtr > weights
ImageTypes< PixelType >::ProcessImageType ProcessImageType
std::vector< vigra::ImageImportInfo > inputFiles
vigra::FRGBImage ImageType
void preprocessImage(unsigned int i, FImagePtr &weight, ProcessImageTypePtr &output)
function to preprocess input image This function loads image, linearize it using EMoR (FIXME)...