在layerModelBlending的PR过程中出现的问题和解决方法
一、情况说明
layerModelBlending是属于photo 模块下的算法,我很大程度上参考seamlessclone进行实现。这是我第一次编写功能模块,不同于之前的教程或者是某些参数的修改。这里的操作需要更多的工作。这里将过程中出现的问题和解决方法进行分析,作为经验。
二、问题分析
主要是修改两个地方,一个是photo.hpp,主要是添加头文件;
//! layerModelBlending algorithm flags
enum
{
DARKEN = 1, //min(Target,Blend)
MULTIPY = 2, //Target * Blend
COLOR_BURN = 3, //1 - (1-Target) / Blend
LINEAR_BRUN = 4, //Target + Blend - 1
LIGHTEN = 5, //max(Target,Blend)
SCREEN = 6, //1 - (1-Target) * (1-Blend)
COLOR_DODGE = 7, //Target / (1-Blend)
LINEAR_DODGE = 8, //Target + Blend
OVERLAY = 9, //(Target > 0.5) * (1 - (1-2*(Target-0.5)) * (1-Blend)) +(Target <= 0.5) * ((2*Target) * Blend)
SOFT_LIGHT = 10, //(Blend > 0.5) * (1 - (1-Target) * (1-(Blend-0.5))) +(Blend <= 0.5) * (Target * (Blend+0.5))
HARD_LIGHT = 11, //(Blend > 0.5) * (1 - (1-Target) * (1-2*(Blend-0.5))) +(Blend <= 0.5) * (Target * (2*Blend))
VIVID_LIGHT = 12, //(Blend > 0.5) * (1 - (1-Target) / (2*(Blend-0.5))) +(Blend <= 0.5) * (Target / (1-2*Blend))
LINEAR_LIGHT = 13, //(Blend > 0.5) * (Target + 2*(Blend-0.5)) +(Blend <= 0.5) * (Target + 2*Blend - 1)
PIN_LIGHT = 14, //(Blend > 0.5) * (max(Target,2*(Blend-0.5))) +(Blend <= 0.5) * (min(Target,2*Blend)))
DIFFERENCE = 15, //| Target - Blend |
EXCLUSION = 16, //0.5 - 2*(Target-0.5)*(Blend-0.5)
DIVIDE = 17 //Target/Blend
};
/** @17 Photoshop blending modes Inspired by GIMP and
http://www.deepskycolors.com/archivo/2010/04/21/formulas-for-Photoshop-blending-modes.html.
@param target and blend Input SAME_SIZE 8-bit 3-channel image.
@param dst Output 8-bit 3-channel image.
@param flags layerModelBlending algorithm : CV::DARKEN、CV::MULTIPY、CV::COLOR_BURN 、CV::LINEAR_BRUN
、CV::LIGHTEN 、CV::SCREEN 、CV::COLOR_DODGE 、CV::LINEAR_DODGE 、CV::OVERLAY、CV::SOFT_LIGHT、CV::HARD_LIGHT、
CV::VIVID_LIGHT、CV::LINEAR_LIGHT、CV::PIN_LIGHT、CV::DIFFERENCE、CV::EXCLUSION 、CV::DIVIDE
*/
CV_EXPORTS_W void layerModelBlending(InputArray target, InputArray blend, OutputArray dst, int flag=1);
//! @} addtogroup layerModelBlending
二个是添加
layerModelBlending
函数实体。
/*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) 2013, OpenCV Foundation, 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*/
#
include
"precomp.hpp"
#
include
"opencv2/photo.hpp"
using
namespace std;
using
namespace cv;
#
define EPSILON
1e
-
6f
#
define SAFE_DIV_MIN EPSILON
#
define SAFE_DIV_MAX (
1.0f
/ SAFE_DIV_MIN)
#
define CLAMP(f,min,max) ((f)
<(min)
?(min)
:(f)
>(max)
?(max)
:(f))
namespace cv
{
/* local function prototypes */
static
inline
float safe_div(
float a,
float b);
/* returns a / b, clamped to [-SAFE_DIV_MAX, SAFE_DIV_MAX].
* if -SAFE_DIV_MIN <= a <= SAFE_DIV_MIN, returns 0.
*/
static
inline
float safe_div(
float a,
float b)
{
float result
=
0.0f;
if (fabsf(a)
> SAFE_DIV_MIN)
{
result
= a
/ b;
result
= CLAMP(result,
-SAFE_DIV_MAX, SAFE_DIV_MAX);
}
return result;
}
CV_EXPORTS_W
void layerModelBlending(InputArray _target, InputArray _blend, OutputArray _dst,
int flag)
{
Mat target
= _target.getMat();
Mat blend
= _blend.getMat();
Mat dst
= _dst.getMat();
for (
int index_row
=
0; index_row
< target.rows; index_row
++)
for (
int index_col
=
0; index_col
< target.cols; index_col
++)
for (
int index_c
=
0; index_c
<
3; index_c
++)
switch (flag)
{
case DARKEN
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
= min(
target.at
<Vec3f
>(index_row, index_col)[index_c],
blend.at
<Vec3f
>(index_row, index_col)[index_c]);
break;
case MULTIPY
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
target.at
<Vec3f
>(index_row, index_col)[index_c]
*
blend.at
<Vec3f
>(index_row, index_col)[index_c];
break;
case COLOR_BURN
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
1
-
safe_div((
1
- target.at
<Vec3f
>(index_row, index_col)[index_c]),
blend.at
<Vec3f
>(index_row, index_col)[index_c]);
break;
case LINEAR_BRUN
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
target.at
<Vec3f
>(index_row, index_col)[index_c]
+
blend.at
<Vec3f
>(index_row, index_col)[index_c]
-
1;
break;
case LIGHTEN
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
= max(
target.at
<Vec3f
>(index_row, index_col)[index_c],
blend.at
<Vec3f
>(index_row, index_col)[index_c]);
break;
case SCREEN
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
1
-
(
1
- target.at
<Vec3f
>(index_row, index_col)[index_c])
*
(
1
- blend.at
<Vec3f
>(index_row, index_col)[index_c]);
break;
case COLOR_DODGE
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
= safe_div
(target.at
<Vec3f
>(index_row, index_col)[index_c],
1
- blend.at
<Vec3f
>(index_row, index_col)[index_c]);
break;
case LINEAR_DODGE
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
target.at
<Vec3f
>(index_row, index_col)[index_c]
+
blend.at
<Vec3f
>(index_row, index_col)[index_c];
break;
case OVERLAY
:
if (target.at
<Vec3f
>(index_row, index_col)[index_c]
>
0.
5f)
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
1
-
(
1
-
2
* (target.at
<Vec3f
>(index_row, index_col)[index_c]
-
0.
5))
*
(
1
- blend.at
<Vec3f
>(index_row, index_col)[index_c]);
else
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
2
*
target.at
<Vec3f
>(index_row, index_col)[index_c]
*
blend.at
<Vec3f
>(index_row, index_col)[index_c];
break;
case SOFT_LIGHT
:
if (target.at
<Vec3f
>(index_row, index_col)[index_c]
>
0.
5f)
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
1
-
(
1
- target.at
<Vec3f
>(index_row, index_col)[index_c])
*
(
1
- (blend.at
<Vec3f
>(index_row, index_col)[index_c]
-
0.
5));
else
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
target.at
<Vec3f
>(index_row, index_col)[index_c]
*
(blend.at
<Vec3f
>(index_row, index_col)[index_c]
+
0.
5);
break;
case HARD_LIGHT
:
if (target.at
<Vec3f
>(index_row, index_col)[index_c]
>
0.
5f)
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
1
-
(
1
- target.at
<Vec3f
>(index_row, index_col)[index_c])
*
(
1
-
2
* blend.at
<Vec3f
>(index_row, index_col)[index_c]
-
0.
5);
else
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
target.at
<Vec3f
>(index_row, index_col)[index_c]
*
(
2
* blend.at
<Vec3f
>(index_row, index_col)[index_c]);
break;
case VIVID_LIGHT
:
if (target.at
<Vec3f
>(index_row, index_col)[index_c]
>
0.
5f)
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
1
-
safe_div(
1
- target.at
<Vec3f
>(index_row, index_col)[index_c],
(
2
* (blend.at
<Vec3f
>(index_row, index_col)[index_c]
-
0.
5)));
else
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
safe_div(target.at
<Vec3f
>(index_row, index_col)[index_c],
(
1
-
2
* blend.at
<Vec3f
>(index_row, index_col)[index_c]));
break;
case LINEAR_LIGHT
:
if (target.at
<Vec3f
>(index_row, index_col)[index_c]
>
0.
5f)
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
target.at
<Vec3f
>(index_row, index_col)[index_c]
+
(
2
* (blend.at
<Vec3f
>(index_row, index_col)[index_c]
-
0.
5));
else
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
target.at
<Vec3f
>(index_row, index_col)[index_c]
+
2
* blend.at
<Vec3f
>(index_row, index_col)[index_c]
-
1;
break;
case PIN_LIGHT
:
if (target.at
<Vec3f
>(index_row, index_col)[index_c]
>
0.
5f)
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
max(target.at
<Vec3f
>(index_row, index_col)[index_c],
(
float)(
2
* (blend.at
<Vec3f
>(index_row, index_col)[index_c]
-
0.
5)));
else
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
min(target.at
<Vec3f
>(index_row, index_col)[index_c],
2
* blend.at
<Vec3f
>(index_row, index_col)[index_c]);
break;
case DIFFERENCE
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
abs(target.at
<Vec3f
>(index_row, index_col)[index_c]
-
blend.at
<Vec3f
>(index_row, index_col)[index_c]);
break;
case EXCLUSION
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
target.at
<Vec3f
>(index_row, index_col)[index_c]
+
blend.at
<Vec3f
>(index_row, index_col)[index_c]
-
2
* target.at
<Vec3f
>(index_row, index_col)[index_c]
* blend.at
<Vec3f
>(index_row, index_col)[index_c];
break;
case DIVIDE
:
dst.at
<Vec3f
>(index_row, index_col)[index_c]
=
safe_div(target.at
<Vec3f
>(index_row, index_col)[index_c],
blend.at
<Vec3f
>(index_row, index_col)[index_c]);
break;
}
}
}
由于有seamlessclone可以参考,所以这里很多东西,虽然繁琐、但是并不是没有解决方法。直到我发现在都设置正确的情况,总是出现link错误。我知道link错误是由于dll文件问题。
经过研究发现:
那么是缺少cv,添加之后。
0000C793
1896
0767
?layerModelBlending@@YAXVMat@cv@@00H@Z
0000AEF7
2297
08F8
?seamlessClone@cv@@YAXAEBV_InputArray@debug_build_guard@
1@00V
?
你发现,我们缺少CV,通过添加namespcae、
能够变成这样
0000A209
1896
0767
?layerModelBlending@cv@@YAXVMat@
1@00H@Z
再发现问题,通过修改形参,便成为:
layerModelBlending@cv@@YAXAEBV_InputArray@debug_build_guard@
1@0AEBV_OutputArray@
31@H@Z
调用成功。
三、反思小结
我在问题出现的地方卡了2天时间,直到去尝试寻找"dll文件结构查看器",才能够定位问题。
使用"dll文件结构查看器"的能力我之前是不具备的,今后是会经常使用的。但是关键在于矛盾之中的思考,也就是处于矛盾情况下,不能一味地重复劳动,而是要跳出圈子,思考根本问题。这才是我记录本BLOG的关键。