bokeh ref iwa fx (#1555)

This commit is contained in:
shun-iwasawa 2017-11-17 17:31:32 +09:00 committed by GitHub
parent eb5f881693
commit e2505a1885
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 1691 additions and 0 deletions

View file

@ -1224,6 +1224,14 @@
<item>"STD_iwa_BokehFx.distance5" "Layer5 Distance"</item>
<item>"STD_iwa_BokehFx.bokeh_adjustment5" "Layer5 Bokeh Adjustment"</item>
<item>"STD_iwa_BokehRefFx" "Bokeh Ref Iwa"</item>
<item>"STD_iwa_BokehRefFx.on_focus_distance" "On-Focus Distance"</item>
<item>"STD_iwa_BokehRefFx.bokeh_amount" "Bokeh Amount"</item>
<item>"STD_iwa_BokehRefFx.hardness" "Hardness"</item>
<item>"STD_iwa_BokehRefFx.distance_precision" "Distance Precision"</item>
<item>"STD_iwa_BokehRefFx.fill_gap" "Fill Gap"</item>
<item>"STD_iwa_BokehRefFx.fill_gap_with_median_filter" "Use Median Filter"</item>
<item>"STD_iwa_TimeCodeFx" "TimeCode Iwa"</item>
<item>"STD_iwa_TimeCodeFx.displayType" "Display Type"</item>
<item>"STD_iwa_TimeCodeFx.frameRate" "Frame Rate"</item>

View file

@ -0,0 +1,59 @@
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Bokeh Fx Iwa</title>
</head>
<body bgcolor="#f5f5f5" text="#220011">
<h1><img src = ".\img\fx_iwa_bokeh_ref.png" width = 30 height = 30 > Bokeh Ref Fx Iwa</h1>
<h4>● 概要</h4>
レンズのボケを再現するエフェクトです。入力画像をデプス参照画像の階調を元に数枚のレイヤーに分割し、
分割された各レイヤーのRGB値を露光値に変換して、絞り形状でボカし、合成します。離散フーリエ変換を使って、高速化を図っています。
ボカし処理を行う前に、各レイヤーの、前景で隠れている部分をメディアンフィルタで延ばす処理を行っています。
<h4>● 入力ポート</h4>
<UL>
<LI><b>Iris</b> : 絞り画像を接続します。入力された画像の輝度値がフィルタに用いられます。Irisポートに何も接続されていない場合は、計算が行われません。RGBA8bit又はRGBA16bit画像が入力できます。
<LI><b>Source</b> : 入力画像を接続します。Sourceポートに何も接続されていない場合は、計算が行われません。
<LI><b>Depth</b> : Depth参照画像を接続します。各ピクセルの輝度がデプスに対応します。値が大きい明るいほど、カメラから遠い位置になります。
</UL>
<h4>● パラメータ</h4>
<UL>
<LI><b>On-Focus Distance</b> : フォーカス位置。この位置にレイヤーがあると、
そのレイヤーはボカされず、通常合成されます。0がカメラ位置です。(範囲 0.01.0)
<LI><b>Bokeh Amount</b> : ボケの最大サイズ(単位 Unit。フォーカス位置とレイヤー位置が 1.0 離れているとき、絞り画像の横幅がこの値になるまで拡大されて用いられます。
<LI><b>Hardness</b> : フィルムのガンマ値。RGB値と露光量の変換に用います。露光量が10倍増えた時の、RGB値0.01.0)の増加量に相当します。この値が小さいほど、ハイライトが強調されます。(範囲 0.053.0)
<LI><b>Distance Precision</b> : デプス参照画像の分割数。この値が大きいほど、ボケサイズの階調が細かくなりますが、処理は遅くなります。(範囲 3128)
</UL>
<h4>● 注意点</h4>
<UL>
<LI>複数フレームをレンダリングする際、レイヤーだけでなくIrisの素材も、レンダリングされるすべてのフレームの範囲に入っている必要があります。
<LI>メモリを多く使います。
</UL>
<h4>● ライセンス情報</h4>
<UL>
<LI>このエフェクトは、フーリエ変換にKiss FFTというオープンソース・ライブラリを用いています。<br>
</UL>
<font size = "-1">
<blockquote>
This is the BSD-style license for the KissFFT.<br>
<br>
Copyright (c) 2003-2010 Mark Borgerding<br>
<br>
All rights reserved.<br>
<br>
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:<br>
<br>
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.<br>
* Redistributions 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.<br>
* Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.<br>
<br>
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 COPYRIGHT OWNER 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.
</blockquote>
</font>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -0,0 +1,12 @@
<fxlayout help_command="iexplore" help_file="BokehRefIwa.html">
<page name="Bokeh Ref Iwa">
<vbox>
<control>on_focus_distance</control>
<control>bokeh_amount</control>
<control>hardness</control>
<control>distance_precision</control>
<control>fill_gap</control>
<control>fill_gap_with_median_filter</control>
</vbox>
</page>
</fxlayout>

View file

@ -21,6 +21,7 @@
STD_rotationalBlurFx
STD_inoSpinBlurFx
STD_iwa_BokehFx
STD_iwa_BokehRefFx
</Blur>
<Distort>
STD_freeDistortFx

View file

@ -131,6 +131,7 @@ const struct {
{"STD_iwa_SpectrumFx", "fx_iwa_spectrum"},
{"STD_iwa_PerspectiveDistortFx", "fx_iwa_perspective_distort"},
{"STD_iwa_BokehFx", "fx_iwa_bokeh"},
{"STD_iwa_BokehRefFx", "fx_iwa_bokeh_ref"},
{"STD_iwa_SoapBubbleFx", "fx_iwa_soapbubble"},
{0, 0}};
};

View file

@ -74,6 +74,7 @@ set(HEADERS
iwa_soapbubblefx.h
iwa_bokehfx.h
iwa_timecodefx.h
iwa_bokehreffx.h
)
set(SOURCES
@ -252,6 +253,7 @@ set(SOURCES
${SDKROOT}/kiss_fft130/tools/kiss_fftnd.c
iwa_bokehfx.cpp
iwa_timecodefx.cpp
iwa_bokehreffx.cpp
)
set(OBJCSOURCES

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,194 @@
#pragma once
/*------------------------------------
Iwa_BokehRefFx
Apply an off-focus effect to a single source image.
The amount of bokeh is specified by user input reference image,
which represents the depth by brightness of pixels.
It considers characteristics of films (which is known as HurterDriffield
curves) or human eye's perception (which is known as WeberFechner law).
For filtering process I used KissFFT, an FFT library by Mark Borgerding,
distributed with a 3-clause BSD-style license.
------------------------------------*/
#ifndef IWA_BOKEH_REF_H
#define IWA_BOKEH_REF_H
#include "stdfx.h"
#include "tfxparam.h"
#include <QVector>
#include <QThread>
#include "tools/kiss_fftnd.h"
struct float4 {
float x, y, z, w;
};
//------------------------------------
class BokehRefThread : public QThread {
int m_channel;
volatile bool m_finished;
kiss_fft_cpx* m_fftcpx_channel_before;
kiss_fft_cpx* m_fftcpx_channel;
kiss_fft_cpx* m_fftcpx_alpha;
kiss_fft_cpx* m_fftcpx_iris;
float4* m_result_buff;
kiss_fftnd_cfg m_kissfft_plan_fwd, m_kissfft_plan_bkwd;
TDimensionI m_dim;
bool m_isTerminated;
public:
BokehRefThread(int channel, kiss_fft_cpx* fftcpx_channel_before,
kiss_fft_cpx* fftcpx_channel, kiss_fft_cpx* fftcpx_alpha,
kiss_fft_cpx* fftcpx_iris, float4* result_buff,
kiss_fftnd_cfg kissfft_plan_fwd,
kiss_fftnd_cfg kissfft_plan_bkwd, TDimensionI& dim);
void run() override;
bool isFinished() { return m_finished; }
void terminateThread() { m_isTerminated = true; }
};
//------------------------------------
class Iwa_BokehRefFx : public TStandardRasterFx {
FX_PLUGIN_DECLARATION(Iwa_BokehRefFx)
protected:
TRasterFxPort m_iris; // iris image
TRasterFxPort m_source; // source image
TRasterFxPort m_depth; // depth reference image
TDoubleParamP m_onFocusDistance; // Focus Distance (0-1)
TDoubleParamP m_bokehAmount; // The maximum bokeh size. The size of bokeh at
// the layer separated by 1.0 from the focal
// position
TDoubleParamP m_hardness; // Film gamma
TIntParamP m_distancePrecision; // Separation of depth image
TBoolParamP m_fillGap; // Toggles whether to extend pixels behind the front
// layers in order to fill gap
// It should be ON for normal backgrounds and should be OFF for the layer
// which is
// "floating" from the lower layers such as dust, snowflake or spider-web.
TBoolParamP m_doMedian; // (Effective only when the Fill Gap option is ON)
// Toggles whether to use Median Filter for extending the pixels.
// Get the pixel size of bokehAmount ( referenced ino_blur.cpp )
float getBokehPixelAmount(const double frame, const TAffine affine);
// normalize the source raster image to 0-1 and set to dstMem
// returns true if the source is (seems to be) premultiplied
template <typename RASTER, typename PIXEL>
bool setSourceRaster(const RASTER srcRas, float4* dstMem, TDimensionI dim);
// normalize brightness of the depth reference image to unsigned char
// and store into dstMem
template <typename RASTER, typename PIXEL>
void setDepthRaster(const RASTER srcRas, unsigned char* dstMem,
TDimensionI dim);
template <typename RASTER, typename PIXEL>
void setDepthRasterGray(const RASTER srcRas, unsigned char* dstMem,
TDimensionI dim);
// create the depth index map
void defineSegemntDepth(const unsigned char* indexMap_main,
const unsigned char* indexMap_sub,
const float* mainSub_ratio,
const unsigned char* depth_buff,
const TDimensionI& dimOut, const double frame,
QVector<float>& segmentDepth_main,
QVector<float>& segmentDepth_sub);
// set the result
template <typename RASTER, typename PIXEL>
void setOutputRaster(float4* srcMem, const RASTER dstRas, TDimensionI dim,
TDimensionI margin);
// obtain iris size from the depth value
float calcIrisSize(const float depth, const float bokehPixelAmount,
const double onFocusDistance);
// resize/invert the iris according to the size ratio
// normalize the brightness
// resize to the output size
void convertIris(const float irisSize, const TRectD& irisBBox,
const TTile& irisTile, const TDimensionI& enlargedDim,
kiss_fft_cpx* fftcpx_iris_before);
// convert source image value rgb -> exposure
void convertRGBToExposure(const float4* source_buff, int size,
float filmGamma, bool sourceIsPremultiplied);
// generate the segment layer source at the current depth
// considering fillGap and doMedian options
void retrieveLayer(const float4* source_buff,
const float4* segment_layer_buff,
const unsigned char* indexMap_mainSub, int index, int lx,
int ly, bool fillGap, bool doMedian, int margin);
// apply single median filter
void doSingleMedian(const float4* source_buff,
const float4* segment_layer_buff,
const unsigned char* indexMap_mainSub, int index, int lx,
int ly, const unsigned char* generation_buff, int curGen);
// normal-composite the layer as is, without filtering
void compositeAsIs(const float4* segment_layer_buff,
const float4* result_buff_mainSub, int size);
// retrieve segment layer image for each channel
void retrieveChannel(const float4* segment_layer_buff, // src
kiss_fft_cpx* fftcpx_r_before, // dst
kiss_fft_cpx* fftcpx_g_before, // dst
kiss_fft_cpx* fftcpx_b_before, // dst
kiss_fft_cpx* fftcpx_a_before, // dst
int size);
// multiply filter on channel
void multiplyFilter(kiss_fft_cpx* fftcpx_channel, // dst
kiss_fft_cpx* fftcpx_iris, // filter
int size);
// normal comosite the alpha channel
void compositeAlpha(const float4* result_buff, // dst
const kiss_fft_cpx* fftcpx_alpha, // alpha
int lx, int ly);
// interpolate main and sub exposures
// convert exposure -> RGB (0-1)
// set to the result
void interpolateExposureAndConvertToRGB(
const float4* result_main_buff, // result1
const float4* result_sub_buff, // result2
const float* mainSub_ratio, // ratio
float filmGamma,
const float4* source_buff, // dst
int size);
public:
Iwa_BokehRefFx();
void doCompute(TTile& tile, double frame, const TRenderSettings& settings);
bool doGetBBox(double frame, TRectD& bBox, const TRenderSettings& info);
bool canHandle(const TRenderSettings& info, double frame);
void doCompute_CPU(const double frame, const TRenderSettings& settings,
float bokehPixelAmount, float maxIrisSize, int margin,
TDimensionI& dimOut, float4* source_buff,
unsigned char* indexMap_main, unsigned char* indexMap_sub,
float* mainSub_ratio, QVector<float>& segmentDepth_main,
QVector<float>& segmentDepth_sub, TTile& irisTile,
TRectD& irisBBox, bool sourceIsPremultiplied);
};
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -296,6 +296,7 @@
<file>Resources/fxicons/fx_iwa_perspective_distort.png</file>
<file>Resources/fxicons/fx_iwa_pn_perspective.png</file>
<file>Resources/fxicons/fx_iwa_bokeh.png</file>
<file>Resources/fxicons/fx_iwa_bokeh_ref.png</file>
<file>Resources/fxicons/fx_iwa_soapbubble.png</file>
<file>Resources/fxicons/fx_unidentified.png</file>
<file>Resources/keyframe_noanim.svg</file>