Starting implement simplex algorithm.
This commit is contained in:
parent
47ce461d97
commit
f2afe64521
@ -1,2 +1,2 @@
|
|||||||
set(the_description "Computational Photography")
|
set(the_description "Generic optimization")
|
||||||
ocv_define_module(photo opencv_imgproc)
|
ocv_define_module(optim)
|
||||||
|
@ -1,161 +0,0 @@
|
|||||||
/*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.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Intel License Agreement
|
|
||||||
// For Open Source Computer Vision Library
|
|
||||||
//
|
|
||||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
|
||||||
// Third party copyrights are property of their respective icvers.
|
|
||||||
//
|
|
||||||
// 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 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*/
|
|
||||||
|
|
||||||
#ifndef __OPENCV_DENOISING_ARRAYS_HPP__
|
|
||||||
#define __OPENCV_DENOISING_ARRAYS_HPP__
|
|
||||||
|
|
||||||
template <class T> struct Array2d {
|
|
||||||
T* a;
|
|
||||||
int n1,n2;
|
|
||||||
bool needToDeallocArray;
|
|
||||||
|
|
||||||
Array2d(const Array2d& array2d):
|
|
||||||
a(array2d.a), n1(array2d.n1), n2(array2d.n2), needToDeallocArray(false)
|
|
||||||
{
|
|
||||||
if (array2d.needToDeallocArray) {
|
|
||||||
// copy constructor for self allocating arrays not supported
|
|
||||||
throw new std::exception();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Array2d(T* _a, int _n1, int _n2):
|
|
||||||
a(_a), n1(_n1), n2(_n2), needToDeallocArray(false) {}
|
|
||||||
|
|
||||||
Array2d(int _n1, int _n2):
|
|
||||||
n1(_n1), n2(_n2), needToDeallocArray(true)
|
|
||||||
{
|
|
||||||
a = new T[n1*n2];
|
|
||||||
}
|
|
||||||
|
|
||||||
~Array2d() {
|
|
||||||
if (needToDeallocArray) {
|
|
||||||
delete[] a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T* operator [] (int i) {
|
|
||||||
return a + i*n2;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline T* row_ptr(int i) {
|
|
||||||
return (*this)[i];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T> struct Array3d {
|
|
||||||
T* a;
|
|
||||||
int n1,n2,n3;
|
|
||||||
bool needToDeallocArray;
|
|
||||||
|
|
||||||
Array3d(T* _a, int _n1, int _n2, int _n3):
|
|
||||||
a(_a), n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(false) {}
|
|
||||||
|
|
||||||
Array3d(int _n1, int _n2, int _n3):
|
|
||||||
n1(_n1), n2(_n2), n3(_n3), needToDeallocArray(true)
|
|
||||||
{
|
|
||||||
a = new T[n1*n2*n3];
|
|
||||||
}
|
|
||||||
|
|
||||||
~Array3d() {
|
|
||||||
if (needToDeallocArray) {
|
|
||||||
delete[] a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Array2d<T> operator [] (int i) {
|
|
||||||
Array2d<T> array2d(a + i*n2*n3, n2, n3);
|
|
||||||
return array2d;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline T* row_ptr(int i1, int i2) {
|
|
||||||
return a + i1*n2*n3 + i2*n3;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T> struct Array4d {
|
|
||||||
T* a;
|
|
||||||
int n1,n2,n3,n4;
|
|
||||||
bool needToDeallocArray;
|
|
||||||
int steps[4];
|
|
||||||
|
|
||||||
void init_steps() {
|
|
||||||
steps[0] = n2*n3*n4;
|
|
||||||
steps[1] = n3*n4;
|
|
||||||
steps[2] = n4;
|
|
||||||
steps[3] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Array4d(T* _a, int _n1, int _n2, int _n3, int _n4):
|
|
||||||
a(_a), n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(false)
|
|
||||||
{
|
|
||||||
init_steps();
|
|
||||||
}
|
|
||||||
|
|
||||||
Array4d(int _n1, int _n2, int _n3, int _n4):
|
|
||||||
n1(_n1), n2(_n2), n3(_n3), n4(_n4), needToDeallocArray(true)
|
|
||||||
{
|
|
||||||
a = new T[n1*n2*n3*n4];
|
|
||||||
init_steps();
|
|
||||||
}
|
|
||||||
|
|
||||||
~Array4d() {
|
|
||||||
if (needToDeallocArray) {
|
|
||||||
delete[] a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Array3d<T> operator [] (int i) {
|
|
||||||
Array3d<T> array3d(a + i*n2*n3*n4, n2, n3, n4);
|
|
||||||
return array3d;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline T* row_ptr(int i1, int i2, int i3) {
|
|
||||||
return a + i1*n2*n3*n4 + i2*n3*n4 + i3*n4;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int step_size(int dimension) {
|
|
||||||
return steps[dimension];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -1,242 +0,0 @@
|
|||||||
/*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.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Intel License Agreement
|
|
||||||
// For Open Source Computer Vision Library
|
|
||||||
//
|
|
||||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
|
||||||
// Third party copyrights are property of their respective icvers.
|
|
||||||
//
|
|
||||||
// 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 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 "precomp.hpp"
|
|
||||||
#include "opencv2/photo.hpp"
|
|
||||||
#include "opencv2/imgproc.hpp"
|
|
||||||
#include "fast_nlmeans_denoising_invoker.hpp"
|
|
||||||
#include "fast_nlmeans_multi_denoising_invoker.hpp"
|
|
||||||
|
|
||||||
void cv::fastNlMeansDenoising( InputArray _src, OutputArray _dst, float h,
|
|
||||||
int templateWindowSize, int searchWindowSize)
|
|
||||||
{
|
|
||||||
Mat src = _src.getMat();
|
|
||||||
_dst.create(src.size(), src.type());
|
|
||||||
Mat dst = _dst.getMat();
|
|
||||||
|
|
||||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
|
||||||
if(tegra::fastNlMeansDenoising(src, dst, h, templateWindowSize, searchWindowSize))
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
switch (src.type()) {
|
|
||||||
case CV_8U:
|
|
||||||
parallel_for(cv::BlockedRange(0, src.rows),
|
|
||||||
FastNlMeansDenoisingInvoker<uchar>(
|
|
||||||
src, dst, templateWindowSize, searchWindowSize, h));
|
|
||||||
break;
|
|
||||||
case CV_8UC2:
|
|
||||||
parallel_for(cv::BlockedRange(0, src.rows),
|
|
||||||
FastNlMeansDenoisingInvoker<cv::Vec2b>(
|
|
||||||
src, dst, templateWindowSize, searchWindowSize, h));
|
|
||||||
break;
|
|
||||||
case CV_8UC3:
|
|
||||||
parallel_for(cv::BlockedRange(0, src.rows),
|
|
||||||
FastNlMeansDenoisingInvoker<cv::Vec3b>(
|
|
||||||
src, dst, templateWindowSize, searchWindowSize, h));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
CV_Error(Error::StsBadArg,
|
|
||||||
"Unsupported image format! Only CV_8UC1, CV_8UC2 and CV_8UC3 are supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cv::fastNlMeansDenoisingColored( InputArray _src, OutputArray _dst,
|
|
||||||
float h, float hForColorComponents,
|
|
||||||
int templateWindowSize, int searchWindowSize)
|
|
||||||
{
|
|
||||||
Mat src = _src.getMat();
|
|
||||||
_dst.create(src.size(), src.type());
|
|
||||||
Mat dst = _dst.getMat();
|
|
||||||
|
|
||||||
if (src.type() != CV_8UC3) {
|
|
||||||
CV_Error(Error::StsBadArg, "Type of input image should be CV_8UC3!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat src_lab;
|
|
||||||
cvtColor(src, src_lab, COLOR_LBGR2Lab);
|
|
||||||
|
|
||||||
Mat l(src.size(), CV_8U);
|
|
||||||
Mat ab(src.size(), CV_8UC2);
|
|
||||||
Mat l_ab[] = { l, ab };
|
|
||||||
int from_to[] = { 0,0, 1,1, 2,2 };
|
|
||||||
mixChannels(&src_lab, 1, l_ab, 2, from_to, 3);
|
|
||||||
|
|
||||||
fastNlMeansDenoising(l, l, h, templateWindowSize, searchWindowSize);
|
|
||||||
fastNlMeansDenoising(ab, ab, hForColorComponents, templateWindowSize, searchWindowSize);
|
|
||||||
|
|
||||||
Mat l_ab_denoised[] = { l, ab };
|
|
||||||
Mat dst_lab(src.size(), src.type());
|
|
||||||
mixChannels(l_ab_denoised, 2, &dst_lab, 1, from_to, 3);
|
|
||||||
|
|
||||||
cvtColor(dst_lab, dst, COLOR_Lab2LBGR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fastNlMeansDenoisingMultiCheckPreconditions(
|
|
||||||
const std::vector<Mat>& srcImgs,
|
|
||||||
int imgToDenoiseIndex, int temporalWindowSize,
|
|
||||||
int templateWindowSize, int searchWindowSize)
|
|
||||||
{
|
|
||||||
int src_imgs_size = (int)srcImgs.size();
|
|
||||||
if (src_imgs_size == 0) {
|
|
||||||
CV_Error(Error::StsBadArg, "Input images vector should not be empty!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (temporalWindowSize % 2 == 0 ||
|
|
||||||
searchWindowSize % 2 == 0 ||
|
|
||||||
templateWindowSize % 2 == 0) {
|
|
||||||
CV_Error(Error::StsBadArg, "All windows sizes should be odd!");
|
|
||||||
}
|
|
||||||
|
|
||||||
int temporalWindowHalfSize = temporalWindowSize / 2;
|
|
||||||
if (imgToDenoiseIndex - temporalWindowHalfSize < 0 ||
|
|
||||||
imgToDenoiseIndex + temporalWindowHalfSize >= src_imgs_size)
|
|
||||||
{
|
|
||||||
CV_Error(Error::StsBadArg,
|
|
||||||
"imgToDenoiseIndex and temporalWindowSize "
|
|
||||||
"should be choosen corresponding srcImgs size!");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i < src_imgs_size; i++) {
|
|
||||||
if (srcImgs[0].size() != srcImgs[i].size() || srcImgs[0].type() != srcImgs[i].type()) {
|
|
||||||
CV_Error(Error::StsBadArg, "Input images should have the same size and type!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cv::fastNlMeansDenoisingMulti( InputArrayOfArrays _srcImgs, OutputArray _dst,
|
|
||||||
int imgToDenoiseIndex, int temporalWindowSize,
|
|
||||||
float h, int templateWindowSize, int searchWindowSize)
|
|
||||||
{
|
|
||||||
std::vector<Mat> srcImgs;
|
|
||||||
_srcImgs.getMatVector(srcImgs);
|
|
||||||
|
|
||||||
fastNlMeansDenoisingMultiCheckPreconditions(
|
|
||||||
srcImgs, imgToDenoiseIndex,
|
|
||||||
temporalWindowSize, templateWindowSize, searchWindowSize
|
|
||||||
);
|
|
||||||
_dst.create(srcImgs[0].size(), srcImgs[0].type());
|
|
||||||
Mat dst = _dst.getMat();
|
|
||||||
|
|
||||||
switch (srcImgs[0].type()) {
|
|
||||||
case CV_8U:
|
|
||||||
parallel_for(cv::BlockedRange(0, srcImgs[0].rows),
|
|
||||||
FastNlMeansMultiDenoisingInvoker<uchar>(
|
|
||||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
|
||||||
dst, templateWindowSize, searchWindowSize, h));
|
|
||||||
break;
|
|
||||||
case CV_8UC2:
|
|
||||||
parallel_for(cv::BlockedRange(0, srcImgs[0].rows),
|
|
||||||
FastNlMeansMultiDenoisingInvoker<cv::Vec2b>(
|
|
||||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
|
||||||
dst, templateWindowSize, searchWindowSize, h));
|
|
||||||
break;
|
|
||||||
case CV_8UC3:
|
|
||||||
parallel_for(cv::BlockedRange(0, srcImgs[0].rows),
|
|
||||||
FastNlMeansMultiDenoisingInvoker<cv::Vec3b>(
|
|
||||||
srcImgs, imgToDenoiseIndex, temporalWindowSize,
|
|
||||||
dst, templateWindowSize, searchWindowSize, h));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
CV_Error(Error::StsBadArg,
|
|
||||||
"Unsupported matrix format! Only uchar, Vec2b, Vec3b are supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cv::fastNlMeansDenoisingColoredMulti( InputArrayOfArrays _srcImgs, OutputArray _dst,
|
|
||||||
int imgToDenoiseIndex, int temporalWindowSize,
|
|
||||||
float h, float hForColorComponents,
|
|
||||||
int templateWindowSize, int searchWindowSize)
|
|
||||||
{
|
|
||||||
std::vector<Mat> srcImgs;
|
|
||||||
_srcImgs.getMatVector(srcImgs);
|
|
||||||
|
|
||||||
fastNlMeansDenoisingMultiCheckPreconditions(
|
|
||||||
srcImgs, imgToDenoiseIndex,
|
|
||||||
temporalWindowSize, templateWindowSize, searchWindowSize
|
|
||||||
);
|
|
||||||
|
|
||||||
_dst.create(srcImgs[0].size(), srcImgs[0].type());
|
|
||||||
Mat dst = _dst.getMat();
|
|
||||||
|
|
||||||
int src_imgs_size = (int)srcImgs.size();
|
|
||||||
|
|
||||||
if (srcImgs[0].type() != CV_8UC3) {
|
|
||||||
CV_Error(Error::StsBadArg, "Type of input images should be CV_8UC3!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int from_to[] = { 0,0, 1,1, 2,2 };
|
|
||||||
|
|
||||||
// TODO convert only required images
|
|
||||||
std::vector<Mat> src_lab(src_imgs_size);
|
|
||||||
std::vector<Mat> l(src_imgs_size);
|
|
||||||
std::vector<Mat> ab(src_imgs_size);
|
|
||||||
for (int i = 0; i < src_imgs_size; i++) {
|
|
||||||
src_lab[i] = Mat::zeros(srcImgs[0].size(), CV_8UC3);
|
|
||||||
l[i] = Mat::zeros(srcImgs[0].size(), CV_8UC1);
|
|
||||||
ab[i] = Mat::zeros(srcImgs[0].size(), CV_8UC2);
|
|
||||||
cvtColor(srcImgs[i], src_lab[i], COLOR_LBGR2Lab);
|
|
||||||
|
|
||||||
Mat l_ab[] = { l[i], ab[i] };
|
|
||||||
mixChannels(&src_lab[i], 1, l_ab, 2, from_to, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat dst_l;
|
|
||||||
Mat dst_ab;
|
|
||||||
|
|
||||||
fastNlMeansDenoisingMulti(
|
|
||||||
l, dst_l, imgToDenoiseIndex, temporalWindowSize,
|
|
||||||
h, templateWindowSize, searchWindowSize);
|
|
||||||
|
|
||||||
fastNlMeansDenoisingMulti(
|
|
||||||
ab, dst_ab, imgToDenoiseIndex, temporalWindowSize,
|
|
||||||
hForColorComponents, templateWindowSize, searchWindowSize);
|
|
||||||
|
|
||||||
Mat l_ab_denoised[] = { dst_l, dst_ab };
|
|
||||||
Mat dst_lab(srcImgs[0].size(), srcImgs[0].type());
|
|
||||||
mixChannels(l_ab_denoised, 2, &dst_lab, 1, from_to, 3);
|
|
||||||
|
|
||||||
cvtColor(dst_lab, dst, COLOR_Lab2LBGR);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,334 +0,0 @@
|
|||||||
/*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.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Intel License Agreement
|
|
||||||
// For Open Source Computer Vision Library
|
|
||||||
//
|
|
||||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
|
||||||
// Third party copyrights are property of their respective icvers.
|
|
||||||
//
|
|
||||||
// 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 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*/
|
|
||||||
|
|
||||||
#ifndef __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_HPP__
|
|
||||||
#define __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_HPP__
|
|
||||||
|
|
||||||
#include "precomp.hpp"
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
#include "fast_nlmeans_denoising_invoker_commons.hpp"
|
|
||||||
#include "arrays.hpp"
|
|
||||||
|
|
||||||
using namespace cv;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct FastNlMeansDenoisingInvoker {
|
|
||||||
public:
|
|
||||||
FastNlMeansDenoisingInvoker(const Mat& src, Mat& dst,
|
|
||||||
int template_window_size, int search_window_size, const float h);
|
|
||||||
|
|
||||||
void operator() (const BlockedRange& range) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void operator= (const FastNlMeansDenoisingInvoker&);
|
|
||||||
|
|
||||||
const Mat& src_;
|
|
||||||
Mat& dst_;
|
|
||||||
|
|
||||||
Mat extended_src_;
|
|
||||||
int border_size_;
|
|
||||||
|
|
||||||
int template_window_size_;
|
|
||||||
int search_window_size_;
|
|
||||||
|
|
||||||
int template_window_half_size_;
|
|
||||||
int search_window_half_size_;
|
|
||||||
|
|
||||||
int fixed_point_mult_;
|
|
||||||
int almost_template_window_size_sq_bin_shift_;
|
|
||||||
std::vector<int> almost_dist2weight_;
|
|
||||||
|
|
||||||
void calcDistSumsForFirstElementInRow(
|
|
||||||
int i,
|
|
||||||
Array2d<int>& dist_sums,
|
|
||||||
Array3d<int>& col_dist_sums,
|
|
||||||
Array3d<int>& up_col_dist_sums) const;
|
|
||||||
|
|
||||||
void calcDistSumsForElementInFirstRow(
|
|
||||||
int i,
|
|
||||||
int j,
|
|
||||||
int first_col_num,
|
|
||||||
Array2d<int>& dist_sums,
|
|
||||||
Array3d<int>& col_dist_sums,
|
|
||||||
Array3d<int>& up_col_dist_sums) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline int getNearestPowerOf2(int value)
|
|
||||||
{
|
|
||||||
int p = 0;
|
|
||||||
while( 1 << p < value) ++p;
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
FastNlMeansDenoisingInvoker<T>::FastNlMeansDenoisingInvoker(
|
|
||||||
const cv::Mat& src,
|
|
||||||
cv::Mat& dst,
|
|
||||||
int template_window_size,
|
|
||||||
int search_window_size,
|
|
||||||
const float h) : src_(src), dst_(dst)
|
|
||||||
{
|
|
||||||
CV_Assert(src.channels() == sizeof(T)); //T is Vec1b or Vec2b or Vec3b
|
|
||||||
|
|
||||||
template_window_half_size_ = template_window_size / 2;
|
|
||||||
search_window_half_size_ = search_window_size / 2;
|
|
||||||
template_window_size_ = template_window_half_size_ * 2 + 1;
|
|
||||||
search_window_size_ = search_window_half_size_ * 2 + 1;
|
|
||||||
|
|
||||||
border_size_ = search_window_half_size_ + template_window_half_size_;
|
|
||||||
copyMakeBorder(src_, extended_src_,
|
|
||||||
border_size_, border_size_, border_size_, border_size_, cv::BORDER_DEFAULT);
|
|
||||||
|
|
||||||
const int max_estimate_sum_value = search_window_size_ * search_window_size_ * 255;
|
|
||||||
fixed_point_mult_ = std::numeric_limits<int>::max() / max_estimate_sum_value;
|
|
||||||
|
|
||||||
// precalc weight for every possible l2 dist between blocks
|
|
||||||
// additional optimization of precalced weights to replace division(averaging) by binary shift
|
|
||||||
|
|
||||||
CV_Assert(template_window_size_ <= 46340 ); // sqrt(INT_MAX)
|
|
||||||
int template_window_size_sq = template_window_size_ * template_window_size_;
|
|
||||||
almost_template_window_size_sq_bin_shift_ = getNearestPowerOf2(template_window_size_sq);
|
|
||||||
double almost_dist2actual_dist_multiplier = ((double)(1 << almost_template_window_size_sq_bin_shift_)) / template_window_size_sq;
|
|
||||||
|
|
||||||
int max_dist = 255 * 255 * sizeof(T);
|
|
||||||
int almost_max_dist = (int) (max_dist / almost_dist2actual_dist_multiplier + 1);
|
|
||||||
almost_dist2weight_.resize(almost_max_dist);
|
|
||||||
|
|
||||||
const double WEIGHT_THRESHOLD = 0.001;
|
|
||||||
for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++) {
|
|
||||||
double dist = almost_dist * almost_dist2actual_dist_multiplier;
|
|
||||||
int weight = cvRound(fixed_point_mult_ * std::exp(-dist / (h * h * sizeof(T))));
|
|
||||||
|
|
||||||
if (weight < WEIGHT_THRESHOLD * fixed_point_mult_)
|
|
||||||
weight = 0;
|
|
||||||
|
|
||||||
almost_dist2weight_[almost_dist] = weight;
|
|
||||||
}
|
|
||||||
CV_Assert(almost_dist2weight_[0] == fixed_point_mult_);
|
|
||||||
// additional optimization init end
|
|
||||||
|
|
||||||
if (dst_.empty()) {
|
|
||||||
dst_ = Mat::zeros(src_.size(), src_.type());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void FastNlMeansDenoisingInvoker<T>::operator() (const BlockedRange& range) const {
|
|
||||||
int row_from = range.begin();
|
|
||||||
int row_to = range.end() - 1;
|
|
||||||
|
|
||||||
Array2d<int> dist_sums(search_window_size_, search_window_size_);
|
|
||||||
|
|
||||||
// for lazy calc optimization
|
|
||||||
Array3d<int> col_dist_sums(template_window_size_, search_window_size_, search_window_size_);
|
|
||||||
|
|
||||||
int first_col_num = -1;
|
|
||||||
Array3d<int> up_col_dist_sums(src_.cols, search_window_size_, search_window_size_);
|
|
||||||
|
|
||||||
for (int i = row_from; i <= row_to; i++) {
|
|
||||||
for (int j = 0; j < src_.cols; j++) {
|
|
||||||
int search_window_y = i - search_window_half_size_;
|
|
||||||
int search_window_x = j - search_window_half_size_;
|
|
||||||
|
|
||||||
// calc dist_sums
|
|
||||||
if (j == 0) {
|
|
||||||
calcDistSumsForFirstElementInRow(i, dist_sums, col_dist_sums, up_col_dist_sums);
|
|
||||||
first_col_num = 0;
|
|
||||||
|
|
||||||
} else { // calc cur dist_sums using previous dist_sums
|
|
||||||
if (i == row_from) {
|
|
||||||
calcDistSumsForElementInFirstRow(i, j, first_col_num,
|
|
||||||
dist_sums, col_dist_sums, up_col_dist_sums);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
int ay = border_size_ + i;
|
|
||||||
int ax = border_size_ + j + template_window_half_size_;
|
|
||||||
|
|
||||||
int start_by =
|
|
||||||
border_size_ + i - search_window_half_size_;
|
|
||||||
|
|
||||||
int start_bx =
|
|
||||||
border_size_ + j - search_window_half_size_ + template_window_half_size_;
|
|
||||||
|
|
||||||
T a_up = extended_src_.at<T>(ay - template_window_half_size_ - 1, ax);
|
|
||||||
T a_down = extended_src_.at<T>(ay + template_window_half_size_, ax);
|
|
||||||
|
|
||||||
// copy class member to local variable for optimization
|
|
||||||
int search_window_size = search_window_size_;
|
|
||||||
|
|
||||||
for (int y = 0; y < search_window_size; y++) {
|
|
||||||
int* dist_sums_row = dist_sums.row_ptr(y);
|
|
||||||
|
|
||||||
int* col_dist_sums_row = col_dist_sums.row_ptr(first_col_num,y);
|
|
||||||
|
|
||||||
int* up_col_dist_sums_row = up_col_dist_sums.row_ptr(j, y);
|
|
||||||
|
|
||||||
const T* b_up_ptr =
|
|
||||||
extended_src_.ptr<T>(start_by - template_window_half_size_ - 1 + y);
|
|
||||||
|
|
||||||
const T* b_down_ptr =
|
|
||||||
extended_src_.ptr<T>(start_by + template_window_half_size_ + y);
|
|
||||||
|
|
||||||
for (int x = 0; x < search_window_size; x++) {
|
|
||||||
dist_sums_row[x] -= col_dist_sums_row[x];
|
|
||||||
|
|
||||||
col_dist_sums_row[x] =
|
|
||||||
up_col_dist_sums_row[x] +
|
|
||||||
calcUpDownDist(
|
|
||||||
a_up, a_down,
|
|
||||||
b_up_ptr[start_bx + x], b_down_ptr[start_bx + x]
|
|
||||||
);
|
|
||||||
|
|
||||||
dist_sums_row[x] += col_dist_sums_row[x];
|
|
||||||
|
|
||||||
up_col_dist_sums_row[x] = col_dist_sums_row[x];
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
first_col_num = (first_col_num + 1) % template_window_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calc weights
|
|
||||||
int weights_sum = 0;
|
|
||||||
|
|
||||||
int estimation[3];
|
|
||||||
for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++) {
|
|
||||||
estimation[channel_num] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int y = 0; y < search_window_size_; y++) {
|
|
||||||
const T* cur_row_ptr = extended_src_.ptr<T>(border_size_ + search_window_y + y);
|
|
||||||
int* dist_sums_row = dist_sums.row_ptr(y);
|
|
||||||
for (int x = 0; x < search_window_size_; x++) {
|
|
||||||
int almostAvgDist =
|
|
||||||
dist_sums_row[x] >> almost_template_window_size_sq_bin_shift_;
|
|
||||||
|
|
||||||
int weight = almost_dist2weight_[almostAvgDist];
|
|
||||||
weights_sum += weight;
|
|
||||||
|
|
||||||
T p = cur_row_ptr[border_size_ + search_window_x + x];
|
|
||||||
incWithWeight(estimation, weight, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++)
|
|
||||||
estimation[channel_num] = ((unsigned)estimation[channel_num] + weights_sum/2) / weights_sum;
|
|
||||||
|
|
||||||
dst_.at<T>(i,j) = saturateCastFromArray<T>(estimation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForFirstElementInRow(
|
|
||||||
int i,
|
|
||||||
Array2d<int>& dist_sums,
|
|
||||||
Array3d<int>& col_dist_sums,
|
|
||||||
Array3d<int>& up_col_dist_sums) const
|
|
||||||
{
|
|
||||||
int j = 0;
|
|
||||||
|
|
||||||
for (int y = 0; y < search_window_size_; y++) {
|
|
||||||
for (int x = 0; x < search_window_size_; x++) {
|
|
||||||
dist_sums[y][x] = 0;
|
|
||||||
for (int tx = 0; tx < template_window_size_; tx++) {
|
|
||||||
col_dist_sums[tx][y][x] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int start_y = i + y - search_window_half_size_;
|
|
||||||
int start_x = j + x - search_window_half_size_;
|
|
||||||
|
|
||||||
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++) {
|
|
||||||
for (int tx = -template_window_half_size_; tx <= template_window_half_size_; tx++) {
|
|
||||||
int dist = calcDist<T>(extended_src_,
|
|
||||||
border_size_ + i + ty, border_size_ + j + tx,
|
|
||||||
border_size_ + start_y + ty, border_size_ + start_x + tx);
|
|
||||||
|
|
||||||
dist_sums[y][x] += dist;
|
|
||||||
col_dist_sums[tx + template_window_half_size_][y][x] += dist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
up_col_dist_sums[j][y][x] = col_dist_sums[template_window_size_ - 1][y][x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline void FastNlMeansDenoisingInvoker<T>::calcDistSumsForElementInFirstRow(
|
|
||||||
int i,
|
|
||||||
int j,
|
|
||||||
int first_col_num,
|
|
||||||
Array2d<int>& dist_sums,
|
|
||||||
Array3d<int>& col_dist_sums,
|
|
||||||
Array3d<int>& up_col_dist_sums) const
|
|
||||||
{
|
|
||||||
int ay = border_size_ + i;
|
|
||||||
int ax = border_size_ + j + template_window_half_size_;
|
|
||||||
|
|
||||||
int start_by = border_size_ + i - search_window_half_size_;
|
|
||||||
int start_bx = border_size_ + j - search_window_half_size_ + template_window_half_size_;
|
|
||||||
|
|
||||||
int new_last_col_num = first_col_num;
|
|
||||||
|
|
||||||
for (int y = 0; y < search_window_size_; y++) {
|
|
||||||
for (int x = 0; x < search_window_size_; x++) {
|
|
||||||
dist_sums[y][x] -= col_dist_sums[first_col_num][y][x];
|
|
||||||
|
|
||||||
col_dist_sums[new_last_col_num][y][x] = 0;
|
|
||||||
int by = start_by + y;
|
|
||||||
int bx = start_bx + x;
|
|
||||||
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++) {
|
|
||||||
col_dist_sums[new_last_col_num][y][x] +=
|
|
||||||
calcDist<T>(extended_src_, ay + ty, ax, by + ty, bx);
|
|
||||||
}
|
|
||||||
|
|
||||||
dist_sums[y][x] += col_dist_sums[new_last_col_num][y][x];
|
|
||||||
|
|
||||||
up_col_dist_sums[j][y][x] = col_dist_sums[new_last_col_num][y][x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,115 +0,0 @@
|
|||||||
/*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.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Intel License Agreement
|
|
||||||
// For Open Source Computer Vision Library
|
|
||||||
//
|
|
||||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
|
||||||
// Third party copyrights are property of their respective icvers.
|
|
||||||
//
|
|
||||||
// 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 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*/
|
|
||||||
|
|
||||||
#ifndef __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_COMMONS_HPP__
|
|
||||||
#define __OPENCV_FAST_NLMEANS_DENOISING_INVOKER_COMMONS_HPP__
|
|
||||||
|
|
||||||
using namespace cv;
|
|
||||||
|
|
||||||
template <typename T> static inline int calcDist(const T a, const T b);
|
|
||||||
|
|
||||||
template <> inline int calcDist(const uchar a, const uchar b) {
|
|
||||||
return (a-b) * (a-b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> inline int calcDist(const Vec2b a, const Vec2b b) {
|
|
||||||
return (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> inline int calcDist(const Vec3b a, const Vec3b b) {
|
|
||||||
return (a[0]-b[0])*(a[0]-b[0]) + (a[1]-b[1])*(a[1]-b[1]) + (a[2]-b[2])*(a[2]-b[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> static inline int calcDist(const Mat& m, int i1, int j1, int i2, int j2) {
|
|
||||||
const T a = m.at<T>(i1, j1);
|
|
||||||
const T b = m.at<T>(i2, j2);
|
|
||||||
return calcDist<T>(a,b);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> static inline int calcUpDownDist(T a_up, T a_down, T b_up, T b_down) {
|
|
||||||
return calcDist(a_down,b_down) - calcDist(a_up, b_up);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> inline int calcUpDownDist(uchar a_up, uchar a_down, uchar b_up, uchar b_down) {
|
|
||||||
int A = a_down - b_down;
|
|
||||||
int B = a_up - b_up;
|
|
||||||
return (A-B)*(A+B);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> static inline void incWithWeight(int* estimation, int weight, T p);
|
|
||||||
|
|
||||||
template <> inline void incWithWeight(int* estimation, int weight, uchar p) {
|
|
||||||
estimation[0] += weight * p;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> inline void incWithWeight(int* estimation, int weight, Vec2b p) {
|
|
||||||
estimation[0] += weight * p[0];
|
|
||||||
estimation[1] += weight * p[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> inline void incWithWeight(int* estimation, int weight, Vec3b p) {
|
|
||||||
estimation[0] += weight * p[0];
|
|
||||||
estimation[1] += weight * p[1];
|
|
||||||
estimation[2] += weight * p[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> static inline T saturateCastFromArray(int* estimation);
|
|
||||||
|
|
||||||
template <> inline uchar saturateCastFromArray(int* estimation) {
|
|
||||||
return saturate_cast<uchar>(estimation[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> inline Vec2b saturateCastFromArray(int* estimation) {
|
|
||||||
Vec2b res;
|
|
||||||
res[0] = saturate_cast<uchar>(estimation[0]);
|
|
||||||
res[1] = saturate_cast<uchar>(estimation[1]);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <> inline Vec3b saturateCastFromArray(int* estimation) {
|
|
||||||
Vec3b res;
|
|
||||||
res[0] = saturate_cast<uchar>(estimation[0]);
|
|
||||||
res[1] = saturate_cast<uchar>(estimation[1]);
|
|
||||||
res[2] = saturate_cast<uchar>(estimation[2]);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,383 +0,0 @@
|
|||||||
/*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.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Intel License Agreement
|
|
||||||
// For Open Source Computer Vision Library
|
|
||||||
//
|
|
||||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
|
||||||
// Third party copyrights are property of their respective icvers.
|
|
||||||
//
|
|
||||||
// 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 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*/
|
|
||||||
|
|
||||||
#ifndef __OPENCV_FAST_NLMEANS_MULTI_DENOISING_INVOKER_HPP__
|
|
||||||
#define __OPENCV_FAST_NLMEANS_MULTI_DENOISING_INVOKER_HPP__
|
|
||||||
|
|
||||||
#include "precomp.hpp"
|
|
||||||
#include <limits>
|
|
||||||
|
|
||||||
#include "fast_nlmeans_denoising_invoker_commons.hpp"
|
|
||||||
#include "arrays.hpp"
|
|
||||||
|
|
||||||
using namespace cv;
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct FastNlMeansMultiDenoisingInvoker {
|
|
||||||
public:
|
|
||||||
FastNlMeansMultiDenoisingInvoker(
|
|
||||||
const std::vector<Mat>& srcImgs, int imgToDenoiseIndex, int temporalWindowSize,
|
|
||||||
Mat& dst, int template_window_size, int search_window_size, const float h);
|
|
||||||
|
|
||||||
void operator() (const BlockedRange& range) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void operator= (const FastNlMeansMultiDenoisingInvoker&);
|
|
||||||
|
|
||||||
int rows_;
|
|
||||||
int cols_;
|
|
||||||
|
|
||||||
Mat& dst_;
|
|
||||||
|
|
||||||
std::vector<Mat> extended_srcs_;
|
|
||||||
Mat main_extended_src_;
|
|
||||||
int border_size_;
|
|
||||||
|
|
||||||
int template_window_size_;
|
|
||||||
int search_window_size_;
|
|
||||||
int temporal_window_size_;
|
|
||||||
|
|
||||||
int template_window_half_size_;
|
|
||||||
int search_window_half_size_;
|
|
||||||
int temporal_window_half_size_;
|
|
||||||
|
|
||||||
int fixed_point_mult_;
|
|
||||||
int almost_template_window_size_sq_bin_shift;
|
|
||||||
std::vector<int> almost_dist2weight;
|
|
||||||
|
|
||||||
void calcDistSumsForFirstElementInRow(
|
|
||||||
int i,
|
|
||||||
Array3d<int>& dist_sums,
|
|
||||||
Array4d<int>& col_dist_sums,
|
|
||||||
Array4d<int>& up_col_dist_sums) const;
|
|
||||||
|
|
||||||
void calcDistSumsForElementInFirstRow(
|
|
||||||
int i,
|
|
||||||
int j,
|
|
||||||
int first_col_num,
|
|
||||||
Array3d<int>& dist_sums,
|
|
||||||
Array4d<int>& col_dist_sums,
|
|
||||||
Array4d<int>& up_col_dist_sums) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
FastNlMeansMultiDenoisingInvoker<T>::FastNlMeansMultiDenoisingInvoker(
|
|
||||||
const std::vector<Mat>& srcImgs,
|
|
||||||
int imgToDenoiseIndex,
|
|
||||||
int temporalWindowSize,
|
|
||||||
cv::Mat& dst,
|
|
||||||
int template_window_size,
|
|
||||||
int search_window_size,
|
|
||||||
const float h) : dst_(dst), extended_srcs_(srcImgs.size())
|
|
||||||
{
|
|
||||||
CV_Assert(srcImgs.size() > 0);
|
|
||||||
CV_Assert(srcImgs[0].channels() == sizeof(T));
|
|
||||||
|
|
||||||
rows_ = srcImgs[0].rows;
|
|
||||||
cols_ = srcImgs[0].cols;
|
|
||||||
|
|
||||||
template_window_half_size_ = template_window_size / 2;
|
|
||||||
search_window_half_size_ = search_window_size / 2;
|
|
||||||
temporal_window_half_size_ = temporalWindowSize / 2;
|
|
||||||
|
|
||||||
template_window_size_ = template_window_half_size_ * 2 + 1;
|
|
||||||
search_window_size_ = search_window_half_size_ * 2 + 1;
|
|
||||||
temporal_window_size_ = temporal_window_half_size_ * 2 + 1;
|
|
||||||
|
|
||||||
border_size_ = search_window_half_size_ + template_window_half_size_;
|
|
||||||
for (int i = 0; i < temporal_window_size_; i++) {
|
|
||||||
copyMakeBorder(
|
|
||||||
srcImgs[imgToDenoiseIndex - temporal_window_half_size_ + i], extended_srcs_[i],
|
|
||||||
border_size_, border_size_, border_size_, border_size_, cv::BORDER_DEFAULT);
|
|
||||||
}
|
|
||||||
main_extended_src_ = extended_srcs_[temporal_window_half_size_];
|
|
||||||
|
|
||||||
const int max_estimate_sum_value =
|
|
||||||
temporal_window_size_ * search_window_size_ * search_window_size_ * 255;
|
|
||||||
|
|
||||||
fixed_point_mult_ = std::numeric_limits<int>::max() / max_estimate_sum_value;
|
|
||||||
|
|
||||||
// precalc weight for every possible l2 dist between blocks
|
|
||||||
// additional optimization of precalced weights to replace division(averaging) by binary shift
|
|
||||||
int template_window_size_sq = template_window_size_ * template_window_size_;
|
|
||||||
almost_template_window_size_sq_bin_shift = 0;
|
|
||||||
while (1 << almost_template_window_size_sq_bin_shift < template_window_size_sq) {
|
|
||||||
almost_template_window_size_sq_bin_shift++;
|
|
||||||
}
|
|
||||||
|
|
||||||
int almost_template_window_size_sq = 1 << almost_template_window_size_sq_bin_shift;
|
|
||||||
double almost_dist2actual_dist_multiplier =
|
|
||||||
((double) almost_template_window_size_sq) / template_window_size_sq;
|
|
||||||
|
|
||||||
int max_dist = 255 * 255 * sizeof(T);
|
|
||||||
int almost_max_dist = (int) (max_dist / almost_dist2actual_dist_multiplier + 1);
|
|
||||||
almost_dist2weight.resize(almost_max_dist);
|
|
||||||
|
|
||||||
const double WEIGHT_THRESHOLD = 0.001;
|
|
||||||
for (int almost_dist = 0; almost_dist < almost_max_dist; almost_dist++) {
|
|
||||||
double dist = almost_dist * almost_dist2actual_dist_multiplier;
|
|
||||||
int weight = cvRound(fixed_point_mult_ * std::exp(-dist / (h * h * sizeof(T))));
|
|
||||||
|
|
||||||
if (weight < WEIGHT_THRESHOLD * fixed_point_mult_) {
|
|
||||||
weight = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
almost_dist2weight[almost_dist] = weight;
|
|
||||||
}
|
|
||||||
CV_Assert(almost_dist2weight[0] == fixed_point_mult_);
|
|
||||||
// additional optimization init end
|
|
||||||
|
|
||||||
if (dst_.empty()) {
|
|
||||||
dst_ = Mat::zeros(srcImgs[0].size(), srcImgs[0].type());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void FastNlMeansMultiDenoisingInvoker<T>::operator() (const BlockedRange& range) const {
|
|
||||||
int row_from = range.begin();
|
|
||||||
int row_to = range.end() - 1;
|
|
||||||
|
|
||||||
Array3d<int> dist_sums(temporal_window_size_, search_window_size_, search_window_size_);
|
|
||||||
|
|
||||||
// for lazy calc optimization
|
|
||||||
Array4d<int> col_dist_sums(
|
|
||||||
template_window_size_, temporal_window_size_, search_window_size_, search_window_size_);
|
|
||||||
|
|
||||||
int first_col_num = -1;
|
|
||||||
|
|
||||||
Array4d<int> up_col_dist_sums(
|
|
||||||
cols_, temporal_window_size_, search_window_size_, search_window_size_);
|
|
||||||
|
|
||||||
for (int i = row_from; i <= row_to; i++) {
|
|
||||||
for (int j = 0; j < cols_; j++) {
|
|
||||||
int search_window_y = i - search_window_half_size_;
|
|
||||||
int search_window_x = j - search_window_half_size_;
|
|
||||||
|
|
||||||
// calc dist_sums
|
|
||||||
if (j == 0) {
|
|
||||||
calcDistSumsForFirstElementInRow(i, dist_sums, col_dist_sums, up_col_dist_sums);
|
|
||||||
first_col_num = 0;
|
|
||||||
|
|
||||||
} else { // calc cur dist_sums using previous dist_sums
|
|
||||||
if (i == row_from) {
|
|
||||||
calcDistSumsForElementInFirstRow(i, j, first_col_num,
|
|
||||||
dist_sums, col_dist_sums, up_col_dist_sums);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
int ay = border_size_ + i;
|
|
||||||
int ax = border_size_ + j + template_window_half_size_;
|
|
||||||
|
|
||||||
int start_by =
|
|
||||||
border_size_ + i - search_window_half_size_;
|
|
||||||
|
|
||||||
int start_bx =
|
|
||||||
border_size_ + j - search_window_half_size_ + template_window_half_size_;
|
|
||||||
|
|
||||||
T a_up = main_extended_src_.at<T>(ay - template_window_half_size_ - 1, ax);
|
|
||||||
T a_down = main_extended_src_.at<T>(ay + template_window_half_size_, ax);
|
|
||||||
|
|
||||||
// copy class member to local variable for optimization
|
|
||||||
int search_window_size = search_window_size_;
|
|
||||||
|
|
||||||
for (int d = 0; d < temporal_window_size_; d++) {
|
|
||||||
Mat cur_extended_src = extended_srcs_[d];
|
|
||||||
Array2d<int> cur_dist_sums = dist_sums[d];
|
|
||||||
Array2d<int> cur_col_dist_sums = col_dist_sums[first_col_num][d];
|
|
||||||
Array2d<int> cur_up_col_dist_sums = up_col_dist_sums[j][d];
|
|
||||||
for (int y = 0; y < search_window_size; y++) {
|
|
||||||
int* dist_sums_row = cur_dist_sums.row_ptr(y);
|
|
||||||
|
|
||||||
int* col_dist_sums_row = cur_col_dist_sums.row_ptr(y);
|
|
||||||
|
|
||||||
int* up_col_dist_sums_row = cur_up_col_dist_sums.row_ptr(y);
|
|
||||||
|
|
||||||
const T* b_up_ptr =
|
|
||||||
cur_extended_src.ptr<T>(start_by - template_window_half_size_ - 1 + y);
|
|
||||||
const T* b_down_ptr =
|
|
||||||
cur_extended_src.ptr<T>(start_by + template_window_half_size_ + y);
|
|
||||||
|
|
||||||
for (int x = 0; x < search_window_size; x++) {
|
|
||||||
dist_sums_row[x] -= col_dist_sums_row[x];
|
|
||||||
|
|
||||||
col_dist_sums_row[x] = up_col_dist_sums_row[x] +
|
|
||||||
calcUpDownDist(
|
|
||||||
a_up, a_down,
|
|
||||||
b_up_ptr[start_bx + x], b_down_ptr[start_bx + x]
|
|
||||||
);
|
|
||||||
|
|
||||||
dist_sums_row[x] += col_dist_sums_row[x];
|
|
||||||
|
|
||||||
up_col_dist_sums_row[x] = col_dist_sums_row[x];
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
first_col_num = (first_col_num + 1) % template_window_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calc weights
|
|
||||||
int weights_sum = 0;
|
|
||||||
|
|
||||||
int estimation[3];
|
|
||||||
for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++) {
|
|
||||||
estimation[channel_num] = 0;
|
|
||||||
}
|
|
||||||
for (int d = 0; d < temporal_window_size_; d++) {
|
|
||||||
const Mat& esrc_d = extended_srcs_[d];
|
|
||||||
for (int y = 0; y < search_window_size_; y++) {
|
|
||||||
const T* cur_row_ptr = esrc_d.ptr<T>(border_size_ + search_window_y + y);
|
|
||||||
|
|
||||||
int* dist_sums_row = dist_sums.row_ptr(d, y);
|
|
||||||
|
|
||||||
for (int x = 0; x < search_window_size_; x++) {
|
|
||||||
int almostAvgDist =
|
|
||||||
dist_sums_row[x] >> almost_template_window_size_sq_bin_shift;
|
|
||||||
|
|
||||||
int weight = almost_dist2weight[almostAvgDist];
|
|
||||||
weights_sum += weight;
|
|
||||||
|
|
||||||
T p = cur_row_ptr[border_size_ + search_window_x + x];
|
|
||||||
incWithWeight(estimation, weight, p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t channel_num = 0; channel_num < sizeof(T); channel_num++)
|
|
||||||
estimation[channel_num] = ((unsigned)estimation[channel_num] + weights_sum / 2) / weights_sum;
|
|
||||||
|
|
||||||
dst_.at<T>(i,j) = saturateCastFromArray<T>(estimation);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline void FastNlMeansMultiDenoisingInvoker<T>::calcDistSumsForFirstElementInRow(
|
|
||||||
int i,
|
|
||||||
Array3d<int>& dist_sums,
|
|
||||||
Array4d<int>& col_dist_sums,
|
|
||||||
Array4d<int>& up_col_dist_sums) const
|
|
||||||
{
|
|
||||||
int j = 0;
|
|
||||||
|
|
||||||
for (int d = 0; d < temporal_window_size_; d++) {
|
|
||||||
Mat cur_extended_src = extended_srcs_[d];
|
|
||||||
for (int y = 0; y < search_window_size_; y++) {
|
|
||||||
for (int x = 0; x < search_window_size_; x++) {
|
|
||||||
dist_sums[d][y][x] = 0;
|
|
||||||
for (int tx = 0; tx < template_window_size_; tx++) {
|
|
||||||
col_dist_sums[tx][d][y][x] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int start_y = i + y - search_window_half_size_;
|
|
||||||
int start_x = j + x - search_window_half_size_;
|
|
||||||
|
|
||||||
int* dist_sums_ptr = &dist_sums[d][y][x];
|
|
||||||
int* col_dist_sums_ptr = &col_dist_sums[0][d][y][x];
|
|
||||||
int col_dist_sums_step = col_dist_sums.step_size(0);
|
|
||||||
for (int tx = -template_window_half_size_; tx <= template_window_half_size_; tx++) {
|
|
||||||
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++) {
|
|
||||||
int dist = calcDist<T>(
|
|
||||||
main_extended_src_.at<T>(
|
|
||||||
border_size_ + i + ty, border_size_ + j + tx),
|
|
||||||
cur_extended_src.at<T>(
|
|
||||||
border_size_ + start_y + ty, border_size_ + start_x + tx)
|
|
||||||
);
|
|
||||||
|
|
||||||
*dist_sums_ptr += dist;
|
|
||||||
*col_dist_sums_ptr += dist;
|
|
||||||
}
|
|
||||||
col_dist_sums_ptr += col_dist_sums_step;
|
|
||||||
}
|
|
||||||
|
|
||||||
up_col_dist_sums[j][d][y][x] = col_dist_sums[template_window_size_ - 1][d][y][x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline void FastNlMeansMultiDenoisingInvoker<T>::calcDistSumsForElementInFirstRow(
|
|
||||||
int i,
|
|
||||||
int j,
|
|
||||||
int first_col_num,
|
|
||||||
Array3d<int>& dist_sums,
|
|
||||||
Array4d<int>& col_dist_sums,
|
|
||||||
Array4d<int>& up_col_dist_sums) const
|
|
||||||
{
|
|
||||||
int ay = border_size_ + i;
|
|
||||||
int ax = border_size_ + j + template_window_half_size_;
|
|
||||||
|
|
||||||
int start_by = border_size_ + i - search_window_half_size_;
|
|
||||||
int start_bx = border_size_ + j - search_window_half_size_ + template_window_half_size_;
|
|
||||||
|
|
||||||
int new_last_col_num = first_col_num;
|
|
||||||
|
|
||||||
for (int d = 0; d < temporal_window_size_; d++) {
|
|
||||||
Mat cur_extended_src = extended_srcs_[d];
|
|
||||||
for (int y = 0; y < search_window_size_; y++) {
|
|
||||||
for (int x = 0; x < search_window_size_; x++) {
|
|
||||||
dist_sums[d][y][x] -= col_dist_sums[first_col_num][d][y][x];
|
|
||||||
|
|
||||||
col_dist_sums[new_last_col_num][d][y][x] = 0;
|
|
||||||
int by = start_by + y;
|
|
||||||
int bx = start_bx + x;
|
|
||||||
|
|
||||||
int* col_dist_sums_ptr = &col_dist_sums[new_last_col_num][d][y][x];
|
|
||||||
for (int ty = -template_window_half_size_; ty <= template_window_half_size_; ty++) {
|
|
||||||
*col_dist_sums_ptr +=
|
|
||||||
calcDist<T>(
|
|
||||||
main_extended_src_.at<T>(ay + ty, ax),
|
|
||||||
cur_extended_src.at<T>(by + ty, bx)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
dist_sums[d][y][x] += col_dist_sums[new_last_col_num][d][y][x];
|
|
||||||
|
|
||||||
up_col_dist_sums[j][d][y][x] = col_dist_sums[new_last_col_num][d][y][x];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,817 +0,0 @@
|
|||||||
/*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.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Intel License Agreement
|
|
||||||
// For Open Source Computer Vision Library
|
|
||||||
//
|
|
||||||
// Copyright (C) 2000, Intel Corporation, all rights reserved.
|
|
||||||
// Third party copyrights are property of their respective icvers.
|
|
||||||
//
|
|
||||||
// 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 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*/
|
|
||||||
|
|
||||||
/* ////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Geometrical transforms on images and matrices: rotation, zoom etc.
|
|
||||||
//
|
|
||||||
// */
|
|
||||||
|
|
||||||
#include "precomp.hpp"
|
|
||||||
#include "opencv2/imgproc/imgproc_c.h"
|
|
||||||
#include "opencv2/photo/photo_c.h"
|
|
||||||
|
|
||||||
#undef CV_MAT_ELEM_PTR_FAST
|
|
||||||
#define CV_MAT_ELEM_PTR_FAST( mat, row, col, pix_size ) \
|
|
||||||
((mat).data.ptr + (size_t)(mat).step*(row) + (pix_size)*(col))
|
|
||||||
|
|
||||||
inline float
|
|
||||||
min4( float a, float b, float c, float d )
|
|
||||||
{
|
|
||||||
a = MIN(a,b);
|
|
||||||
c = MIN(c,d);
|
|
||||||
return MIN(a,c);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CV_MAT_3COLOR_ELEM(img,type,y,x,c) CV_MAT_ELEM(img,type,y,(x)*3+(c))
|
|
||||||
#define KNOWN 0 //known outside narrow band
|
|
||||||
#define BAND 1 //narrow band (known)
|
|
||||||
#define INSIDE 2 //unknown
|
|
||||||
#define CHANGE 3 //servise
|
|
||||||
|
|
||||||
typedef struct CvHeapElem
|
|
||||||
{
|
|
||||||
float T;
|
|
||||||
int i,j;
|
|
||||||
struct CvHeapElem* prev;
|
|
||||||
struct CvHeapElem* next;
|
|
||||||
}
|
|
||||||
CvHeapElem;
|
|
||||||
|
|
||||||
|
|
||||||
class CvPriorityQueueFloat
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
CvHeapElem *mem,*empty,*head,*tail;
|
|
||||||
int num,in;
|
|
||||||
|
|
||||||
public:
|
|
||||||
bool Init( const CvMat* f )
|
|
||||||
{
|
|
||||||
int i,j;
|
|
||||||
for( i = num = 0; i < f->rows; i++ )
|
|
||||||
{
|
|
||||||
for( j = 0; j < f->cols; j++ )
|
|
||||||
num += CV_MAT_ELEM(*f,uchar,i,j)!=0;
|
|
||||||
}
|
|
||||||
if (num<=0) return false;
|
|
||||||
mem = (CvHeapElem*)cvAlloc((num+2)*sizeof(CvHeapElem));
|
|
||||||
if (mem==NULL) return false;
|
|
||||||
|
|
||||||
head = mem;
|
|
||||||
head->i = head->j = -1;
|
|
||||||
head->prev = NULL;
|
|
||||||
head->next = mem+1;
|
|
||||||
head->T = -FLT_MAX;
|
|
||||||
empty = mem+1;
|
|
||||||
for (i=1; i<=num; i++) {
|
|
||||||
mem[i].prev = mem+i-1;
|
|
||||||
mem[i].next = mem+i+1;
|
|
||||||
mem[i].i = -1;
|
|
||||||
mem[i].T = FLT_MAX;
|
|
||||||
}
|
|
||||||
tail = mem+i;
|
|
||||||
tail->i = tail->j = -1;
|
|
||||||
tail->prev = mem+i-1;
|
|
||||||
tail->next = NULL;
|
|
||||||
tail->T = FLT_MAX;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Add(const CvMat* f) {
|
|
||||||
int i,j;
|
|
||||||
for (i=0; i<f->rows; i++) {
|
|
||||||
for (j=0; j<f->cols; j++) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j)!=0) {
|
|
||||||
if (!Push(i,j,0)) return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Push(int i, int j, float T) {
|
|
||||||
CvHeapElem *tmp=empty,*add=empty;
|
|
||||||
if (empty==tail) return false;
|
|
||||||
while (tmp->prev->T>T) tmp = tmp->prev;
|
|
||||||
if (tmp!=empty) {
|
|
||||||
add->prev->next = add->next;
|
|
||||||
add->next->prev = add->prev;
|
|
||||||
empty = add->next;
|
|
||||||
add->prev = tmp->prev;
|
|
||||||
add->next = tmp;
|
|
||||||
add->prev->next = add;
|
|
||||||
add->next->prev = add;
|
|
||||||
} else {
|
|
||||||
empty = empty->next;
|
|
||||||
}
|
|
||||||
add->i = i;
|
|
||||||
add->j = j;
|
|
||||||
add->T = T;
|
|
||||||
in++;
|
|
||||||
// printf("push i %3d j %3d T %12.4e in %4d\n",i,j,T,in);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Pop(int *i, int *j) {
|
|
||||||
CvHeapElem *tmp=head->next;
|
|
||||||
if (empty==tmp) return false;
|
|
||||||
*i = tmp->i;
|
|
||||||
*j = tmp->j;
|
|
||||||
tmp->prev->next = tmp->next;
|
|
||||||
tmp->next->prev = tmp->prev;
|
|
||||||
tmp->prev = empty->prev;
|
|
||||||
tmp->next = empty;
|
|
||||||
tmp->prev->next = tmp;
|
|
||||||
tmp->next->prev = tmp;
|
|
||||||
empty = tmp;
|
|
||||||
in--;
|
|
||||||
// printf("pop i %3d j %3d T %12.4e in %4d\n",tmp->i,tmp->j,tmp->T,in);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Pop(int *i, int *j, float *T) {
|
|
||||||
CvHeapElem *tmp=head->next;
|
|
||||||
if (empty==tmp) return false;
|
|
||||||
*i = tmp->i;
|
|
||||||
*j = tmp->j;
|
|
||||||
*T = tmp->T;
|
|
||||||
tmp->prev->next = tmp->next;
|
|
||||||
tmp->next->prev = tmp->prev;
|
|
||||||
tmp->prev = empty->prev;
|
|
||||||
tmp->next = empty;
|
|
||||||
tmp->prev->next = tmp;
|
|
||||||
tmp->next->prev = tmp;
|
|
||||||
empty = tmp;
|
|
||||||
in--;
|
|
||||||
// printf("pop i %3d j %3d T %12.4e in %4d\n",tmp->i,tmp->j,tmp->T,in);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CvPriorityQueueFloat(void) {
|
|
||||||
num=in=0;
|
|
||||||
mem=empty=head=tail=NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
~CvPriorityQueueFloat(void)
|
|
||||||
{
|
|
||||||
cvFree( &mem );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline float VectorScalMult(CvPoint2D32f v1,CvPoint2D32f v2) {
|
|
||||||
return v1.x*v2.x+v1.y*v2.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline float VectorLength(CvPoint2D32f v1) {
|
|
||||||
return v1.x*v1.x+v1.y*v1.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
//HEAP::iterator Heap_Iterator;
|
|
||||||
//HEAP Heap;
|
|
||||||
|
|
||||||
static float FastMarching_solve(int i1,int j1,int i2,int j2, const CvMat* f, const CvMat* t)
|
|
||||||
{
|
|
||||||
double sol, a11, a22, m12;
|
|
||||||
a11=CV_MAT_ELEM(*t,float,i1,j1);
|
|
||||||
a22=CV_MAT_ELEM(*t,float,i2,j2);
|
|
||||||
m12=MIN(a11,a22);
|
|
||||||
|
|
||||||
if( CV_MAT_ELEM(*f,uchar,i1,j1) != INSIDE )
|
|
||||||
if( CV_MAT_ELEM(*f,uchar,i2,j2) != INSIDE )
|
|
||||||
if( fabs(a11-a22) >= 1.0 )
|
|
||||||
sol = 1+m12;
|
|
||||||
else
|
|
||||||
sol = (a11+a22+sqrt((double)(2-(a11-a22)*(a11-a22))))*0.5;
|
|
||||||
else
|
|
||||||
sol = 1+a11;
|
|
||||||
else if( CV_MAT_ELEM(*f,uchar,i2,j2) != INSIDE )
|
|
||||||
sol = 1+a22;
|
|
||||||
else
|
|
||||||
sol = 1+m12;
|
|
||||||
|
|
||||||
return (float)sol;
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
icvCalcFMM(const CvMat *f, CvMat *t, CvPriorityQueueFloat *Heap, bool negate) {
|
|
||||||
int i, j, ii = 0, jj = 0, q;
|
|
||||||
float dist;
|
|
||||||
|
|
||||||
while (Heap->Pop(&ii,&jj)) {
|
|
||||||
|
|
||||||
unsigned known=(negate)?CHANGE:KNOWN;
|
|
||||||
CV_MAT_ELEM(*f,uchar,ii,jj) = (uchar)known;
|
|
||||||
|
|
||||||
for (q=0; q<4; q++) {
|
|
||||||
i=0; j=0;
|
|
||||||
if (q==0) {i=ii-1; j=jj;}
|
|
||||||
else if(q==1) {i=ii; j=jj-1;}
|
|
||||||
else if(q==2) {i=ii+1; j=jj;}
|
|
||||||
else {i=ii; j=jj+1;}
|
|
||||||
if ((i<=0)||(j<=0)||(i>f->rows)||(j>f->cols)) continue;
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
|
|
||||||
dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
|
|
||||||
FastMarching_solve(i+1,j,i,j-1,f,t),
|
|
||||||
FastMarching_solve(i-1,j,i,j+1,f,t),
|
|
||||||
FastMarching_solve(i+1,j,i,j+1,f,t));
|
|
||||||
CV_MAT_ELEM(*t,float,i,j) = dist;
|
|
||||||
CV_MAT_ELEM(*f,uchar,i,j) = BAND;
|
|
||||||
Heap->Push(i,j,dist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (negate) {
|
|
||||||
for (i=0; i<f->rows; i++) {
|
|
||||||
for(j=0; j<f->cols; j++) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j) == CHANGE) {
|
|
||||||
CV_MAT_ELEM(*f,uchar,i,j) = KNOWN;
|
|
||||||
CV_MAT_ELEM(*t,float,i,j) = -CV_MAT_ELEM(*t,float,i,j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap ) {
|
|
||||||
int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0;
|
|
||||||
float dist;
|
|
||||||
|
|
||||||
if (CV_MAT_CN(out->type)==3) {
|
|
||||||
|
|
||||||
while (Heap->Pop(&ii,&jj)) {
|
|
||||||
|
|
||||||
CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
|
|
||||||
for(q=0; q<4; q++) {
|
|
||||||
if (q==0) {i=ii-1; j=jj;}
|
|
||||||
else if(q==1) {i=ii; j=jj-1;}
|
|
||||||
else if(q==2) {i=ii+1; j=jj;}
|
|
||||||
else if(q==3) {i=ii; j=jj+1;}
|
|
||||||
if ((i<=1)||(j<=1)||(i>t->rows-1)||(j>t->cols-1)) continue;
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
|
|
||||||
dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
|
|
||||||
FastMarching_solve(i+1,j,i,j-1,f,t),
|
|
||||||
FastMarching_solve(i-1,j,i,j+1,f,t),
|
|
||||||
FastMarching_solve(i+1,j,i,j+1,f,t));
|
|
||||||
CV_MAT_ELEM(*t,float,i,j) = dist;
|
|
||||||
|
|
||||||
for (color=0; color<=2; color++) {
|
|
||||||
CvPoint2D32f gradI,gradT,r;
|
|
||||||
float Ia=0,Jx=0,Jy=0,s=1.0e-20f,w,dst,lev,dir,sat;
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j+1)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
|
|
||||||
gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j-1)))*0.5f;
|
|
||||||
} else {
|
|
||||||
gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
|
|
||||||
gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i,j-1)));
|
|
||||||
} else {
|
|
||||||
gradT.x=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i+1,j)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
|
|
||||||
gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i-1,j)))*0.5f;
|
|
||||||
} else {
|
|
||||||
gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i,j)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
|
|
||||||
gradT.y=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i-1,j)));
|
|
||||||
} else {
|
|
||||||
gradT.y=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (k=i-range; k<=i+range; k++) {
|
|
||||||
int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
|
|
||||||
for (l=j-range; l<=j+range; l++) {
|
|
||||||
int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
|
|
||||||
if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
|
|
||||||
if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
|
|
||||||
((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
|
|
||||||
r.y = (float)(i-k);
|
|
||||||
r.x = (float)(j-l);
|
|
||||||
|
|
||||||
dst = (float)(1./(VectorLength(r)*sqrt((double)VectorLength(r))));
|
|
||||||
lev = (float)(1./(1+fabs(CV_MAT_ELEM(*t,float,k,l)-CV_MAT_ELEM(*t,float,i,j))));
|
|
||||||
|
|
||||||
dir=VectorScalMult(r,gradT);
|
|
||||||
if (fabs(dir)<=0.01) dir=0.000001f;
|
|
||||||
w = (float)fabs(dst*lev*dir);
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
|
||||||
gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)))*2.0f;
|
|
||||||
} else {
|
|
||||||
gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
|
||||||
gradI.x=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,km,lp,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)));
|
|
||||||
} else {
|
|
||||||
gradI.x=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
|
||||||
gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)))*2.0f;
|
|
||||||
} else {
|
|
||||||
gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
|
||||||
gradI.y=(float)((CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)));
|
|
||||||
} else {
|
|
||||||
gradI.y=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ia += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color));
|
|
||||||
Jx -= (float)w * (float)(gradI.x*r.x);
|
|
||||||
Jy -= (float)w * (float)(gradI.y*r.y);
|
|
||||||
s += w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sat = (float)((Ia/s+(Jx+Jy)/(sqrt(Jx*Jx+Jy*Jy)+1.0e-20f)+0.5f));
|
|
||||||
{
|
|
||||||
CV_MAT_3COLOR_ELEM(*out,uchar,i-1,j-1,color) = cv::saturate_cast<uchar>(sat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CV_MAT_ELEM(*f,uchar,i,j) = BAND;
|
|
||||||
Heap->Push(i,j,dist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (CV_MAT_CN(out->type)==1) {
|
|
||||||
|
|
||||||
while (Heap->Pop(&ii,&jj)) {
|
|
||||||
|
|
||||||
CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
|
|
||||||
for(q=0; q<4; q++) {
|
|
||||||
if (q==0) {i=ii-1; j=jj;}
|
|
||||||
else if(q==1) {i=ii; j=jj-1;}
|
|
||||||
else if(q==2) {i=ii+1; j=jj;}
|
|
||||||
else if(q==3) {i=ii; j=jj+1;}
|
|
||||||
if ((i<=1)||(j<=1)||(i>t->rows-1)||(j>t->cols-1)) continue;
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
|
|
||||||
dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
|
|
||||||
FastMarching_solve(i+1,j,i,j-1,f,t),
|
|
||||||
FastMarching_solve(i-1,j,i,j+1,f,t),
|
|
||||||
FastMarching_solve(i+1,j,i,j+1,f,t));
|
|
||||||
CV_MAT_ELEM(*t,float,i,j) = dist;
|
|
||||||
|
|
||||||
for (color=0; color<=0; color++) {
|
|
||||||
CvPoint2D32f gradI,gradT,r;
|
|
||||||
float Ia=0,Jx=0,Jy=0,s=1.0e-20f,w,dst,lev,dir,sat;
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j+1)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
|
|
||||||
gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j-1)))*0.5f;
|
|
||||||
} else {
|
|
||||||
gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j+1)-CV_MAT_ELEM(*t,float,i,j)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j-1)!=INSIDE) {
|
|
||||||
gradT.x=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i,j-1)));
|
|
||||||
} else {
|
|
||||||
gradT.x=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i+1,j)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
|
|
||||||
gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i-1,j)))*0.5f;
|
|
||||||
} else {
|
|
||||||
gradT.y=(float)((CV_MAT_ELEM(*t,float,i+1,j)-CV_MAT_ELEM(*t,float,i,j)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i-1,j)!=INSIDE) {
|
|
||||||
gradT.y=(float)((CV_MAT_ELEM(*t,float,i,j)-CV_MAT_ELEM(*t,float,i-1,j)));
|
|
||||||
} else {
|
|
||||||
gradT.y=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (k=i-range; k<=i+range; k++) {
|
|
||||||
int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
|
|
||||||
for (l=j-range; l<=j+range; l++) {
|
|
||||||
int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
|
|
||||||
if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
|
|
||||||
if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
|
|
||||||
((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
|
|
||||||
r.y = (float)(i-k);
|
|
||||||
r.x = (float)(j-l);
|
|
||||||
|
|
||||||
dst = (float)(1./(VectorLength(r)*sqrt(VectorLength(r))));
|
|
||||||
lev = (float)(1./(1+fabs(CV_MAT_ELEM(*t,float,k,l)-CV_MAT_ELEM(*t,float,i,j))));
|
|
||||||
|
|
||||||
dir=VectorScalMult(r,gradT);
|
|
||||||
if (fabs(dir)<=0.01) dir=0.000001f;
|
|
||||||
w = (float)fabs(dst*lev*dir);
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
|
||||||
gradI.x=(float)((CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm-1)))*2.0f;
|
|
||||||
} else {
|
|
||||||
gradI.x=(float)((CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
|
||||||
gradI.x=(float)((CV_MAT_ELEM(*out,uchar,km,lp)-CV_MAT_ELEM(*out,uchar,km,lm-1)));
|
|
||||||
} else {
|
|
||||||
gradI.x=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
|
||||||
gradI.y=(float)((CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)))*2.0f;
|
|
||||||
} else {
|
|
||||||
gradI.y=(float)((CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,km,lm)));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
|
||||||
gradI.y=(float)((CV_MAT_ELEM(*out,uchar,kp,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)));
|
|
||||||
} else {
|
|
||||||
gradI.y=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ia += (float)w * (float)(CV_MAT_ELEM(*out,uchar,km,lm));
|
|
||||||
Jx -= (float)w * (float)(gradI.x*r.x);
|
|
||||||
Jy -= (float)w * (float)(gradI.y*r.y);
|
|
||||||
s += w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sat = (float)((Ia/s+(Jx+Jy)/(sqrt(Jx*Jx+Jy*Jy)+1.0e-20f)+0.5f));
|
|
||||||
{
|
|
||||||
CV_MAT_ELEM(*out,uchar,i-1,j-1) = cv::saturate_cast<uchar>(sat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CV_MAT_ELEM(*f,uchar,i,j) = BAND;
|
|
||||||
Heap->Push(i,j,dist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
icvNSInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQueueFloat *Heap) {
|
|
||||||
int i = 0, j = 0, ii = 0, jj = 0, k, l, q, color = 0;
|
|
||||||
float dist;
|
|
||||||
|
|
||||||
if (CV_MAT_CN(out->type)==3) {
|
|
||||||
|
|
||||||
while (Heap->Pop(&ii,&jj)) {
|
|
||||||
|
|
||||||
CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
|
|
||||||
for(q=0; q<4; q++) {
|
|
||||||
if (q==0) {i=ii-1; j=jj;}
|
|
||||||
else if(q==1) {i=ii; j=jj-1;}
|
|
||||||
else if(q==2) {i=ii+1; j=jj;}
|
|
||||||
else if(q==3) {i=ii; j=jj+1;}
|
|
||||||
if ((i<=1)||(j<=1)||(i>t->rows-1)||(j>t->cols-1)) continue;
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
|
|
||||||
dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
|
|
||||||
FastMarching_solve(i+1,j,i,j-1,f,t),
|
|
||||||
FastMarching_solve(i-1,j,i,j+1,f,t),
|
|
||||||
FastMarching_solve(i+1,j,i,j+1,f,t));
|
|
||||||
CV_MAT_ELEM(*t,float,i,j) = dist;
|
|
||||||
|
|
||||||
for (color=0; color<=2; color++) {
|
|
||||||
CvPoint2D32f gradI,r;
|
|
||||||
float Ia=0,s=1.0e-20f,w,dst,dir;
|
|
||||||
|
|
||||||
for (k=i-range; k<=i+range; k++) {
|
|
||||||
int km=k-1+(k==1),kp=k-1-(k==f->rows-2);
|
|
||||||
for (l=j-range; l<=j+range; l++) {
|
|
||||||
int lm=l-1+(l==1),lp=l-1-(l==f->cols-2);
|
|
||||||
if (k>0&&l>0&&k<f->rows-1&&l<f->cols-1) {
|
|
||||||
if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
|
|
||||||
((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
|
|
||||||
r.y=(float)(k-i);
|
|
||||||
r.x=(float)(l-j);
|
|
||||||
|
|
||||||
dst = 1/(VectorLength(r)*VectorLength(r)+1);
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
|
||||||
gradI.x=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color))+
|
|
||||||
abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)));
|
|
||||||
} else {
|
|
||||||
gradI.x=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp+1,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)))*2.0f;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
|
||||||
gradI.x=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,kp,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km-1,lm,color)))*2.0f;
|
|
||||||
} else {
|
|
||||||
gradI.x=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
|
||||||
gradI.y=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color))+
|
|
||||||
abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)));
|
|
||||||
} else {
|
|
||||||
gradI.y=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lp+1,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)))*2.0f;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
|
||||||
gradI.y=(float)(abs(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color)-CV_MAT_3COLOR_ELEM(*out,uchar,km,lm-1,color)))*2.0f;
|
|
||||||
} else {
|
|
||||||
gradI.y=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gradI.x=-gradI.x;
|
|
||||||
dir=VectorScalMult(r,gradI);
|
|
||||||
|
|
||||||
if (fabs(dir)<=0.01) {
|
|
||||||
dir=0.000001f;
|
|
||||||
} else {
|
|
||||||
dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI)));
|
|
||||||
}
|
|
||||||
w = dst*dir;
|
|
||||||
Ia += (float)w * (float)(CV_MAT_3COLOR_ELEM(*out,uchar,km,lm,color));
|
|
||||||
s += w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CV_MAT_3COLOR_ELEM(*out,uchar,i-1,j-1,color) = cv::saturate_cast<uchar>((double)Ia/s);
|
|
||||||
}
|
|
||||||
|
|
||||||
CV_MAT_ELEM(*f,uchar,i,j) = BAND;
|
|
||||||
Heap->Push(i,j,dist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (CV_MAT_CN(out->type)==1) {
|
|
||||||
|
|
||||||
while (Heap->Pop(&ii,&jj)) {
|
|
||||||
|
|
||||||
CV_MAT_ELEM(*f,uchar,ii,jj) = KNOWN;
|
|
||||||
for(q=0; q<4; q++) {
|
|
||||||
if (q==0) {i=ii-1; j=jj;}
|
|
||||||
else if(q==1) {i=ii; j=jj-1;}
|
|
||||||
else if(q==2) {i=ii+1; j=jj;}
|
|
||||||
else if(q==3) {i=ii; j=jj+1;}
|
|
||||||
if ((i<=1)||(j<=1)||(i>t->rows-1)||(j>t->cols-1)) continue;
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,i,j)==INSIDE) {
|
|
||||||
dist = min4(FastMarching_solve(i-1,j,i,j-1,f,t),
|
|
||||||
FastMarching_solve(i+1,j,i,j-1,f,t),
|
|
||||||
FastMarching_solve(i-1,j,i,j+1,f,t),
|
|
||||||
FastMarching_solve(i+1,j,i,j+1,f,t));
|
|
||||||
CV_MAT_ELEM(*t,float,i,j) = dist;
|
|
||||||
|
|
||||||
{
|
|
||||||
CvPoint2D32f gradI,r;
|
|
||||||
float Ia=0,s=1.0e-20f,w,dst,dir;
|
|
||||||
|
|
||||||
for (k=i-range; k<=i+range; k++) {
|
|
||||||
int km=k-1+(k==1),kp=k-1-(k==t->rows-2);
|
|
||||||
for (l=j-range; l<=j+range; l++) {
|
|
||||||
int lm=l-1+(l==1),lp=l-1-(l==t->cols-2);
|
|
||||||
if (k>0&&l>0&&k<t->rows-1&&l<t->cols-1) {
|
|
||||||
if ((CV_MAT_ELEM(*f,uchar,k,l)!=INSIDE)&&
|
|
||||||
((l-j)*(l-j)+(k-i)*(k-i)<=range*range)) {
|
|
||||||
r.y=(float)(i-k);
|
|
||||||
r.x=(float)(j-l);
|
|
||||||
|
|
||||||
dst = 1/(VectorLength(r)*VectorLength(r)+1);
|
|
||||||
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k+1,l)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
|
||||||
gradI.x=(float)(abs(CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,kp,lm))+
|
|
||||||
abs(CV_MAT_ELEM(*out,uchar,kp,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)));
|
|
||||||
} else {
|
|
||||||
gradI.x=(float)(abs(CV_MAT_ELEM(*out,uchar,kp+1,lm)-CV_MAT_ELEM(*out,uchar,kp,lm)))*2.0f;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k-1,l)!=INSIDE) {
|
|
||||||
gradI.x=(float)(abs(CV_MAT_ELEM(*out,uchar,kp,lm)-CV_MAT_ELEM(*out,uchar,km-1,lm)))*2.0f;
|
|
||||||
} else {
|
|
||||||
gradI.x=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l+1)!=INSIDE) {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
|
||||||
gradI.y=(float)(abs(CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm))+
|
|
||||||
abs(CV_MAT_ELEM(*out,uchar,km,lm)-CV_MAT_ELEM(*out,uchar,km,lm-1)));
|
|
||||||
} else {
|
|
||||||
gradI.y=(float)(abs(CV_MAT_ELEM(*out,uchar,km,lp+1)-CV_MAT_ELEM(*out,uchar,km,lm)))*2.0f;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (CV_MAT_ELEM(*f,uchar,k,l-1)!=INSIDE) {
|
|
||||||
gradI.y=(float)(abs(CV_MAT_ELEM(*out,uchar,km,lm)-CV_MAT_ELEM(*out,uchar,km,lm-1)))*2.0f;
|
|
||||||
} else {
|
|
||||||
gradI.y=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
gradI.x=-gradI.x;
|
|
||||||
dir=VectorScalMult(r,gradI);
|
|
||||||
|
|
||||||
if (fabs(dir)<=0.01) {
|
|
||||||
dir=0.000001f;
|
|
||||||
} else {
|
|
||||||
dir = (float)fabs(VectorScalMult(r,gradI)/sqrt(VectorLength(r)*VectorLength(gradI)));
|
|
||||||
}
|
|
||||||
w = dst*dir;
|
|
||||||
Ia += (float)w * (float)(CV_MAT_ELEM(*out,uchar,km,lm));
|
|
||||||
s += w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CV_MAT_ELEM(*out,uchar,i-1,j-1) = cv::saturate_cast<uchar>((double)Ia/s);
|
|
||||||
}
|
|
||||||
|
|
||||||
CV_MAT_ELEM(*f,uchar,i,j) = BAND;
|
|
||||||
Heap->Push(i,j,dist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SET_BORDER1_C1(image,type,value) {\
|
|
||||||
int i,j;\
|
|
||||||
for(j=0; j<image->cols; j++) {\
|
|
||||||
CV_MAT_ELEM(*image,type,0,j) = value;\
|
|
||||||
}\
|
|
||||||
for (i=1; i<image->rows-1; i++) {\
|
|
||||||
CV_MAT_ELEM(*image,type,i,0) = CV_MAT_ELEM(*image,type,i,image->cols-1) = value;\
|
|
||||||
}\
|
|
||||||
for(j=0; j<image->cols; j++) {\
|
|
||||||
CV_MAT_ELEM(*image,type,erows-1,j) = value;\
|
|
||||||
}\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define COPY_MASK_BORDER1_C1(src,dst,type) {\
|
|
||||||
int i,j;\
|
|
||||||
for (i=0; i<src->rows; i++) {\
|
|
||||||
for(j=0; j<src->cols; j++) {\
|
|
||||||
if (CV_MAT_ELEM(*src,type,i,j)!=0)\
|
|
||||||
CV_MAT_ELEM(*dst,type,i+1,j+1) = INSIDE;\
|
|
||||||
}\
|
|
||||||
}\
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace cv {
|
|
||||||
template<> void cv::Ptr<IplConvKernel>::delete_obj()
|
|
||||||
{
|
|
||||||
cvReleaseStructuringElement(&obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
cvInpaint( const CvArr* _input_img, const CvArr* _inpaint_mask, CvArr* _output_img,
|
|
||||||
double inpaintRange, int flags )
|
|
||||||
{
|
|
||||||
cv::Ptr<CvMat> mask, band, f, t, out;
|
|
||||||
cv::Ptr<CvPriorityQueueFloat> Heap, Out;
|
|
||||||
cv::Ptr<IplConvKernel> el_cross, el_range;
|
|
||||||
|
|
||||||
CvMat input_hdr, mask_hdr, output_hdr;
|
|
||||||
CvMat* input_img, *inpaint_mask, *output_img;
|
|
||||||
int range=cvRound(inpaintRange);
|
|
||||||
int erows, ecols;
|
|
||||||
|
|
||||||
input_img = cvGetMat( _input_img, &input_hdr );
|
|
||||||
inpaint_mask = cvGetMat( _inpaint_mask, &mask_hdr );
|
|
||||||
output_img = cvGetMat( _output_img, &output_hdr );
|
|
||||||
|
|
||||||
if( !CV_ARE_SIZES_EQ(input_img,output_img) || !CV_ARE_SIZES_EQ(input_img,inpaint_mask))
|
|
||||||
CV_Error( CV_StsUnmatchedSizes, "All the input and output images must have the same size" );
|
|
||||||
|
|
||||||
if( (CV_MAT_TYPE(input_img->type) != CV_8UC1 &&
|
|
||||||
CV_MAT_TYPE(input_img->type) != CV_8UC3) ||
|
|
||||||
!CV_ARE_TYPES_EQ(input_img,output_img) )
|
|
||||||
CV_Error( CV_StsUnsupportedFormat,
|
|
||||||
"Only 8-bit 1-channel and 3-channel input/output images are supported" );
|
|
||||||
|
|
||||||
if( CV_MAT_TYPE(inpaint_mask->type) != CV_8UC1 )
|
|
||||||
CV_Error( CV_StsUnsupportedFormat, "The mask must be 8-bit 1-channel image" );
|
|
||||||
|
|
||||||
range = MAX(range,1);
|
|
||||||
range = MIN(range,100);
|
|
||||||
|
|
||||||
ecols = input_img->cols + 2;
|
|
||||||
erows = input_img->rows + 2;
|
|
||||||
|
|
||||||
f = cvCreateMat(erows, ecols, CV_8UC1);
|
|
||||||
t = cvCreateMat(erows, ecols, CV_32FC1);
|
|
||||||
band = cvCreateMat(erows, ecols, CV_8UC1);
|
|
||||||
mask = cvCreateMat(erows, ecols, CV_8UC1);
|
|
||||||
el_cross = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CROSS,NULL);
|
|
||||||
|
|
||||||
cvCopy( input_img, output_img );
|
|
||||||
cvSet(mask,cvScalar(KNOWN,0,0,0));
|
|
||||||
COPY_MASK_BORDER1_C1(inpaint_mask,mask,uchar);
|
|
||||||
SET_BORDER1_C1(mask,uchar,0);
|
|
||||||
cvSet(f,cvScalar(KNOWN,0,0,0));
|
|
||||||
cvSet(t,cvScalar(1.0e6f,0,0,0));
|
|
||||||
cvDilate(mask,band,el_cross,1); // image with narrow band
|
|
||||||
Heap=new CvPriorityQueueFloat;
|
|
||||||
if (!Heap->Init(band))
|
|
||||||
return;
|
|
||||||
cvSub(band,mask,band,NULL);
|
|
||||||
SET_BORDER1_C1(band,uchar,0);
|
|
||||||
if (!Heap->Add(band))
|
|
||||||
return;
|
|
||||||
cvSet(f,cvScalar(BAND,0,0,0),band);
|
|
||||||
cvSet(f,cvScalar(INSIDE,0,0,0),mask);
|
|
||||||
cvSet(t,cvScalar(0,0,0,0),band);
|
|
||||||
|
|
||||||
if( flags == cv::INPAINT_TELEA )
|
|
||||||
{
|
|
||||||
out = cvCreateMat(erows, ecols, CV_8UC1);
|
|
||||||
el_range = cvCreateStructuringElementEx(2*range+1,2*range+1,
|
|
||||||
range,range,CV_SHAPE_RECT,NULL);
|
|
||||||
cvDilate(mask,out,el_range,1);
|
|
||||||
cvSub(out,mask,out,NULL);
|
|
||||||
Out=new CvPriorityQueueFloat;
|
|
||||||
if (!Out->Init(out))
|
|
||||||
return;
|
|
||||||
if (!Out->Add(band))
|
|
||||||
return;
|
|
||||||
cvSub(out,band,out,NULL);
|
|
||||||
SET_BORDER1_C1(out,uchar,0);
|
|
||||||
icvCalcFMM(out,t,Out,true);
|
|
||||||
icvTeleaInpaintFMM(mask,t,output_img,range,Heap);
|
|
||||||
}
|
|
||||||
else if (flags == cv::INPAINT_NS) {
|
|
||||||
icvNSInpaintFMM(mask,t,output_img,range,Heap);
|
|
||||||
} else {
|
|
||||||
CV_Error( cv::Error::StsBadArg, "The flags argument must be one of CV_INPAINT_TELEA or CV_INPAINT_NS" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void cv::inpaint( InputArray _src, InputArray _mask, OutputArray _dst,
|
|
||||||
double inpaintRange, int flags )
|
|
||||||
{
|
|
||||||
Mat src = _src.getMat(), mask = _mask.getMat();
|
|
||||||
_dst.create( src.size(), src.type() );
|
|
||||||
CvMat c_src = src, c_mask = mask, c_dst = _dst.getMat();
|
|
||||||
cvInpaint( &c_src, &c_mask, &c_dst, inpaintRange, flags );
|
|
||||||
}
|
|
45
modules/optim/src/lpsolver.cpp
Normal file
45
modules/optim/src/lpsolver.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include "opencv2/opencv.hpp"
|
||||||
|
|
||||||
|
namespace cv {
|
||||||
|
namespace optim {
|
||||||
|
|
||||||
|
class Solver : public Algorithm /* Algorithm is base OpenCV class */
|
||||||
|
{
|
||||||
|
class Function
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~Function() {}
|
||||||
|
virtual double calc(InputArray args) const = 0;
|
||||||
|
virtual double calc(InputArgs, OutputArray grad) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
// could be reused for all the generic algorithms like downhill simplex.
|
||||||
|
virtual void solve(InputArray x0, OutputArray result) const = 0;
|
||||||
|
|
||||||
|
virtual void setTermCriteria(const TermCriteria& criteria) = 0;
|
||||||
|
virtual TermCriteria getTermCriteria() = 0;
|
||||||
|
|
||||||
|
// more detailed API to be defined later ...
|
||||||
|
};
|
||||||
|
|
||||||
|
class LPSolver : public Solver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void solve(InputArray coeffs, InputArray constraints, OutputArray result) const = 0;
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
|
||||||
|
Ptr<LPSolver> createLPSimplexSolver();
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
/*===============
|
||||||
|
Hill climbing solver is more generic one:*/
|
||||||
|
/*
|
||||||
|
class DownhillSolver : public Solver
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// various setters and getters, if needed
|
||||||
|
};
|
||||||
|
|
||||||
|
Ptr<DownhillSolver> createDownhillSolver(const Ptr<Solver::Function>& func);*/
|
@ -1,44 +0,0 @@
|
|||||||
/*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.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// Intel License Agreement
|
|
||||||
// For Open Source Computer Vision Library
|
|
||||||
//
|
|
||||||
// Copyright (C) 2000, Intel Corporation, 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 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 "precomp.hpp"
|
|
||||||
|
|
||||||
/* End of file. */
|
|
@ -1,53 +0,0 @@
|
|||||||
/*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, 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_PRECOMP_H__
|
|
||||||
#define __OPENCV_PRECOMP_H__
|
|
||||||
|
|
||||||
#include "opencv2/photo.hpp"
|
|
||||||
#include "opencv2/core/private.hpp"
|
|
||||||
|
|
||||||
#ifdef HAVE_TEGRA_OPTIMIZATION
|
|
||||||
#include "opencv2/photo/photo_tegra.hpp"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user