Commit 1aad484c authored by Bellaktris's avatar Bellaktris

first inpainting code

parent cb207705
set(the_description "Addon to basic photo module")
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef)
ocv_define_module(xphoto opencv_core opencv_imgproc OPTIONAL opencv_photo opencv_highgui)
\ No newline at end of file
ocv_define_module(xphoto opencv_core opencv_imgproc opencv_stitching OPTIONAL opencv_photo opencv_highgui)
\ No newline at end of file
......@@ -44,6 +44,7 @@
#define __OPENCV_EDGEDETECTION_HPP__
#include "opencv2/xphoto.hpp"
#include "opencv2/xphoto/inpainting.hpp"
#include "opencv2/xphoto/simple_color_balance.hpp"
#include "opencv2/xphoto/dct_image_denoising.hpp"
#endif
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_INPAINTING_HPP__
#define __OPENCV_INPAINTING_HPP__
/*
* inpainting.hpp
*
* Created on: Jul 22, 2014
* Author: Yury Gitman
*/
#include <opencv2/core.hpp>
/*! \namespace cv
Namespace where all the C++ OpenCV functionality resides
*/
namespace cv
{
//! various inpainting algorithms
enum
{
INPAINT_SHIFTMAP = 0
};
/*! The function reconstructs the selected image area from known area.
* \param src : source image.
* \param mask : inpainting mask, 8-bit 1-channel image. Zero pixels indicate the area that needs to be inpainted.
* \param dst : destination image.
* \param algorithmType : inpainting method.
*/
CV_EXPORTS_W void inpaint(const Mat &src, const Mat &mask, Mat &dst, const int algorithmType);
}
#endif // __OPENCV_INPAINTING_HPP__
\ No newline at end of file
#include "opencv2/xphoto.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc/types_c.h"
const char* keys =
{
"{i || input image name}"
"{m || mask image name}"
"{o || output image name}"
};
int main( int argc, const char** argv )
{
bool printHelp = ( argc == 1 );
printHelp = printHelp || ( argc == 2 && std::string(argv[1]) == "--help" );
printHelp = printHelp || ( argc == 2 && std::string(argv[1]) == "-h" );
if ( printHelp )
{
printf("\nThis sample demonstrates shift-map image inpainting\n"
"Call:\n"
" inpainting -i=<string> -m=<string> [-o=<string>]\n\n");
return 0;
}
cv::CommandLineParser parser(argc, argv, keys);
if ( !parser.check() )
{
parser.printErrors();
return -1;
}
std::string inFilename = parser.get<std::string>("i");
std::string maskFilename = parser.get<std::string>("m");
std::string outFilename = parser.get<std::string>("o");
cv::Mat src = cv::imread(inFilename, -1);
if ( src.empty() )
{
printf( "Cannot read image file: %s\n", inFilename.c_str() );
return -1;
}
cv::Mat mask = cv::imread(maskFilename, 0);
if ( mask.empty() )
{
printf( "Cannot read image file: %s\n", maskFilename.c_str() );
return -1;
}
cv::Mat res(src.size(), src.type());
cv::inpaint( src, mask, res, cv::INPAINT_SHIFTMAP );
if ( outFilename == "" )
{
cv::namedWindow("denoising result", 1);
cv::imshow("denoising result", res);
cv::waitKey(0);
}
else
cv::imwrite(outFilename, res);
return 0;
}
\ No newline at end of file
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of Intel Corporation may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <time.h>
#include "opencv2/xphoto.hpp"
#include "../../../../opencv_main/modules/imgproc/src/gcgraph.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/stitching.hpp"
#include "opencv2/core.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/core/types.hpp"
#include "opencv2/core/types_c.h"
namespace cv
{
template <typename Tp1, typename Tp2> static inline Tp2 sqr(Tp1 arg) { return arg * arg; }
template <typename Tp> static inline Tp sqr(Tp arg) { return arg * arg; }
static inline float norm2(const float &a, const float &b) { return sqr(a - b); }
static inline float norm2(const Vec2f &a, const Vec2f &b) { return (a - b).dot(a - b); }
static inline float norm2(const Vec3f &a, const Vec3f &b) { return (a - b).dot(a - b); }
static inline float norm2(const Vec4f &a, const Vec4f &b) { return (a - b).dot(a - b); }
#define dist(imgs, l1, l2, idx1, idx2) ( norm2(imgs[l1](idx1), imgs[l2](idx1)) \
+ norm2(imgs[l1](idx2), imgs[l2](idx2)) )
template <typename Tp>
static inline void setWeights(GCGraph <float> &graph,
const std::vector < Mat_<Tp> > &imgs, const int A, const int B,
const int labelA, const int labelB, const int alpha,
const Point &pointA, const Point &pointB)
{
//************************************************************//
//************************************************************//
if (labelA == labelB)
{
double weightAB = dist( imgs, labelA, alpha, pointA, pointB );
graph.addEdges(A, B, weightAB, weightAB);
}
else
{
double weightAX = dist( imgs, labelA, alpha, pointA, pointB );
double weightXB = dist( imgs, alpha, labelB, pointA, pointB );
double weightXSink = dist( imgs, labelA, labelB, pointA, pointB );
int X = graph.addVtx();
graph.addEdges(A, X, weightAX, weightAX);
graph.addEdges(X, B, weightXB, weightXB);
graph.addTermWeights(X, 0, weightXSink);
}
}
template <typename Tp>
static double alphaExpansion(const std::vector < Mat_<Tp> > &imgs,
const std::vector < Mat_<uchar> > &masks,
const Mat_<int> &labeling, const int alpha, Mat_<int> &nlabeling)
{
//************************************************************//
//************************************************************//
const int height = imgs[0].rows;
const int width = imgs[0].cols;
const double infinity = 10000000000;
const int actualEdges = height*(width - 1) + width*(height - 1);
GCGraph <float> graph(height*width + actualEdges, 2*actualEdges);
// terminal links
for (int i = 0; i < height; ++i)
{
const uchar *maskAlphaRow = masks[alpha].ptr(i);
const int *labelRow = (const int *) labeling.ptr(i);
for (int j = 0; j < width; ++j)
graph.addTermWeights( graph.addVtx(),
maskAlphaRow[j] ? 0 : infinity,
masks[ labelRow[j] ](i, j) ? 0 : infinity );
}
// neighbor links
for (int i = 0; i < height - 1; ++i)
{
const int *currentRow = (const int *) labeling.ptr(i);
const int *nextRow = (const int *) labeling.ptr(i + 1);
for (int j = 0; j < width - 1; ++j)
{
setWeights( graph, imgs, i*width + j, i*width + (j + 1),
currentRow[j], currentRow[j + 1], alpha,
Point(i, j), Point(i, j + 1) );
setWeights( graph, imgs, i*width + j, (i + 1)*width + j,
currentRow[j], nextRow[j], alpha,
Point(i, j), Point(i + 1, j) );
}
}
double result = graph.maxFlow();
nlabeling.create( labeling.size() );
for (int i = 0; i < height; ++i)
{
const int *inRow = (const int *) labeling.ptr(i);
int *outRow = (int *) nlabeling.ptr(i);
for (int j = 0; j < width; ++j)
{
bool gPart = graph.inSourceSegment(i*width + j);
outRow[j] = gPart ? inRow[j] : alpha;
}
}
return result;
}
template <typename Tp>
static void shiftMapInpaint(const Mat_<Tp> &src, const Mat_<uchar> &mask, Mat_<Tp> &dst)
{
//************************************************************//
//************************************************************//
const int nTransform = 60; // number of dominant transforms for stitching
const int psize = 8; // single ANNF patch size
const int width = src.cols;
const int height = src.rows;
Mat_<uchar> invMask = 255 - mask;
dilate(invMask, invMask, Mat(), Point(-1,-1), 2);
/** Downsample **/
//...
/** ANNF computation **/
int init = time(NULL);
srand( 1406297336 );
std::cout << init << std::endl;
std::vector <Matx33f> transforms; // dominant transforms
for (int i = 0; i < nTransform; ++i)
{
float dx = rand()%width - width/2;
float dy = rand()%height - height/2;
transforms.push_back( Matx33f( 1, 0, dx,
0, 1, dy,
0, 0, 1) );
}
/** Warping **/
std::vector < Mat_<Tp> > imgs( nTransform + 1 ); // source image transformed with transforms[i]
std::vector < Mat_<uchar> > masks( nTransform + 1 ); // validity mask for current shift
src.copyTo( imgs[0] );
mask.copyTo( masks[0] );
for (int i = 0; i < nTransform; ++i)
{
Mat_<Tp> nsrc( src.size() );
warpPerspective( src, nsrc, transforms[i], src.size(),
INTER_LINEAR, BORDER_CONSTANT, 0 );
Mat_<uchar> nmask( mask.size(), mask.type() );
warpPerspective( mask, nmask, transforms[i], mask.size(),
INTER_NEAREST, BORDER_CONSTANT, 0 );
nmask &= invMask;
nsrc.copyTo( imgs[i + 1] );
nmask.copyTo( masks[i + 1] );
}
/** Stitching **/
std::vector <double> costs( nTransform + 1 );
std::vector < Mat_<int> > labelings( nTransform + 1 );
Mat_<int> labeling( height, width, 0 );
double cost = std::numeric_limits<double>::max();
for (int success = false, num = 0; ; success = false)
{
for (int i = 0; i < nTransform + 1; ++i)
costs[i] = alphaExpansion(imgs, masks, labeling, i, labelings[i]);
for (int i = 0; i < nTransform + 1; ++i)
if (costs[i] < 0.98*cost)
{
success = true;
cost = costs[num = i];
}
if (success == false)
break;
labelings[num].copyTo(labeling);
}
for (int k = 0; k < height*width; ++k)
{
int i = k / width;
int j = k % width;
dst(i, j) = imgs[labeling(i, j)](i, j);
}
/** Upsample and refinement **/
//...
}
template <typename Tp>
void inpaint(const Mat_<Tp> src, const Mat_<uchar> mask, Mat_<Tp> dst, const int algorithmType)
{
//************************************************************//
//************************************************************//
dst.create( src.size() );
switch ( algorithmType )
{
case INPAINT_SHIFTMAP:
shiftMapInpaint(src, mask, dst);
break;
default:
CV_Assert( false );
break;
}
}
/*! The function reconstructs the selected image area from known area.
* \param src : source image.
* \param mask : inpainting mask, 8-bit 1-channel image. Zero pixels indicate the area that needs to be inpainted.
* \param dst : destination image.
* \param algorithmType : inpainting method.
*/
void inpaint(const Mat &src, const Mat &mask, Mat &dst, const int algorithmType)
{
//************************************************************//
//************************************************************//
CV_Assert( mask.channels() == 1 && mask.depth() == CV_8U );
CV_Assert( src.rows == mask.rows && src.cols == mask.cols );
switch ( src.type() )
{
case CV_8UC1:
inpaint( Mat_<uchar>(src), Mat_<uchar>(mask), Mat_<uchar>(dst), algorithmType );
break;
case CV_8UC2:
inpaint( Mat_<Vec2b>(src), Mat_<uchar>(mask), Mat_<Vec2b>(dst), algorithmType );
break;
case CV_8UC3:
inpaint( Mat_<Vec3b>(src), Mat_<uchar>(mask), Mat_<Vec3b>(dst), algorithmType );
break;
case CV_8UC4:
inpaint( Mat_<Vec4b>(src), Mat_<uchar>(mask), Mat_<Vec4b>(dst), algorithmType );
break;
case CV_16SC1:
inpaint( Mat_<short>(src), Mat_<uchar>(mask), Mat_<short>(dst), algorithmType );
break;
case CV_16SC2:
inpaint( Mat_<Vec2s>(src), Mat_<uchar>(mask), Mat_<Vec2s>(dst), algorithmType );
break;
case CV_16SC3:
inpaint( Mat_<Vec3s>(src), Mat_<uchar>(mask), Mat_<Vec3s>(dst), algorithmType );
break;
case CV_16SC4:
inpaint( Mat_<Vec4s>(src), Mat_<uchar>(mask), Mat_<Vec4s>(dst), algorithmType );
break;
case CV_32SC1:
inpaint( Mat_<int>(src), Mat_<uchar>(mask), Mat_<int>(dst), algorithmType );
break;
case CV_32SC2:
inpaint( Mat_<Vec2i>(src), Mat_<uchar>(mask), Mat_<Vec2i>(dst), algorithmType );
break;
case CV_32SC3:
inpaint( Mat_<Vec3i>(src), Mat_<uchar>(mask), Mat_<Vec3i>(dst), algorithmType );
break;
case CV_32SC4:
inpaint( Mat_<Vec4i>(src), Mat_<uchar>(mask), Mat_<Vec4i>(dst), algorithmType );
break;
case CV_32FC1:
inpaint( Mat_<float>(src), Mat_<uchar>(mask), Mat_<float>(dst), algorithmType);
break;
case CV_32FC2:
inpaint( Mat_<Vec2f>(src), Mat_<uchar>(mask), Mat_<Vec2f>(dst), algorithmType );
break;
case CV_32FC3:
inpaint( Mat_<Vec3f>(src), Mat_<uchar>(mask), Mat_<Vec3f>(dst), algorithmType );
break;
case CV_32FC4:
inpaint( Mat_<Vec4f>(src), Mat_<uchar>(mask), Mat_<Vec4f>(dst), algorithmType );
break;
case CV_64FC1:
inpaint( Mat_<double>(src), Mat_<uchar>(mask), Mat_<double>(dst), algorithmType );
break;
case CV_64FC2:
inpaint( Mat_<Vec2d>(src), Mat_<uchar>(mask), Mat_<Vec2d>(dst), algorithmType );
break;
case CV_64FC3:
inpaint( Mat_<Vec3d>(src), Mat_<uchar>(mask), Mat_<Vec3d>(dst), algorithmType );
break;
case CV_64FC4:
inpaint( Mat_<Vec4d>(src), Mat_<uchar>(mask), Mat_<Vec4d>(dst), algorithmType );
break;
default:
CV_Assert( false );
break;
}
}
}
\ No newline at end of file
......@@ -20,11 +20,6 @@ namespace cvtest
cv::String previousResultName = dir + cv::format( "results/%02d.png", i + 1 );
cv::Mat previousResult = cv::imread( previousResultName, 1 );
cv::Mat sqrError = ( src - previousResult ).mul( src - previousResult );
cv::Scalar mse = cv::sum(sqrError) / cv::Scalar::all( sqrError.total()*sqrError.channels() );
double psnr = 10*log10(3*255*255/(mse[0] + mse[1] + mse[2]));
cv::Mat currentResult, fastNlMeansResult;
cv::dctDenoising(src, currentResult, sigma[i], psize[i]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment