[OpenCV實戰]32 使用OpenCV進行非真實感渲染

目錄

1 保邊濾波的頻域變換

1.1 保邊濾波器Edge Preserving Filter

1.1.1 函數調用

1.1.2 edgePreservingFilter結果

1.2 細節增強

1.3 素描濾波器

1.4 風格化濾波器

2 代碼

3 參考


有人認爲使用高斯內核簡單地模糊圖像,檢測邊緣,並將兩個圖像組合以獲得上面所示卡通化圖像。雖然在大多數區域中所有圖像看起來都很平滑之後,邊緣會被保留。結果看起來很荒謬; 這是一個糟糕的主意。通過雙邊濾波可以完成這項工作,雙邊濾波可能是計算機視覺中最常用的邊緣平滑濾波器,但它很慢。你永遠不會在實時應用程序中使用它。我很高興看到在OpenCV 3中非常快速地實現了保邊濾波器。結果與雙邊濾波非常相似,但速度更快。這是SIGGRAPH 2011論文Domain transform for edge-aware image and video processing實現。論文作者爲Eduardo Gastal and Manuel Oliveira。論文見:

http://www.inf.ufrgs.br/~eslgastal/DomainTransform/Gastal_Oliveira_SIGGRAPH2011_Domain_Transform.pdf

保邊濾波器詳細見:

https://blog.csdn.net/eejieyang/article/details/52333112

1 保邊濾波的頻域變換

作者Eduardo Gastal在他的項目頁面上提供了很多材料來解釋論文及其應用。詳細鏈接見:

http://www.inf.ufrgs.br/~eslgastal/DomainTransform/

在OpenCV 3中,本文使用Photo模塊下的Computational Photography子模塊中的四個函數實現。以下部分通過示例解釋這些功能及其參數。在所有示例中,我們將使用下面的圖像作爲輸入圖像。

1.1 保邊濾波器Edge Preserving Filter

1.1.1 函數調用

OpenCV中保邊濾波器調用函數爲edgePreservingFilter。

函數具體調用如下:

C++:

edgePreservingFilter(Mat src, Mat dst, int flags=1, float sigma_s=60, float sigma_r=0.4f)

Python:

dst = cv2.edgePreservingFilter(src, flags=1, sigma_s=60, sigma_r=0.4)

函數具體參數如下:

SRC:8位3通道輸入圖像

DST:8位3通道輸出圖像

Flag:保變濾波器類型。取值RECURS_FILTER(遞歸濾波)= 1和NORMCONV_FILTER(歸一化卷積)= 2。使用RECURS_FILTER選項比NORMCONV_FILTER快約3.5倍。但NORMCONV_FILTER產生邊緣銳化。當不希望銳化時,要求速度應該使用RECURS_FILTER。

sigma_s:範圍在0到200之間(詳見下文)

sigma_r:範圍在0到1之間(詳見下文)

參數sigma_s和sigma_r是什麼意思?

圖像處理和計算機視覺中的大多數平滑濾波器(例如高斯濾波器或盒式濾波器)具有稱爲sigma_s(用於Sigma_Spatial)的參數,其確定平滑量。典型的平滑濾波器通過其鄰居的加權和來替換像素的值。鄰域越大,過濾後的圖像越平滑。鄰域的大小與參數sigma_s成正比。

在保邊濾波器中,有兩個相互競爭的目標:a)平滑圖像b)不平滑邊緣/顏色邊界。換句話說,我們不能簡單地用它的鄰居的加權和來代替像素的顏色。相反,我們想要將像素中的顏色值替換爲鄰域中的像素的平均值,使其也具有與像素類似的顏色。所以我們有兩個參數:sigma_s和sigma_r。就像其他平滑濾波器一樣,sigma_s控制鄰域的大小,sigma_r(用於sigma_range)控制鄰域內的不同顏色的平均值。較大的sigma_r導致大面積的恆定顏色區域。

1.1.2 edgePreservingFilter結果

將edgePreservingFilter與RECURS_FILTER一起應用的結果如下所示:

施加edgePreservingFilter與NORMCONV_FILTER的結果如下所示:

正如您所看到的,兩個結果非常接近,因此我建議使用  RECURS_FILTER, 因爲它比NORMCONV_FILTER快。

1.2 細節增強

顧名思義,過濾器可以增強細節,使圖像更清晰。調用參數如下:

C++:

detailEnhance(Mat src, Mat dst, float sigma_s=10, float sigma_r=0.15f)

Python:

dst = cv2.detailEnhance(src, sigma_s=10, sigma_r=0.15)

參數與保邊濾波器調用相同。下圖顯示了結果細節增強過濾器。請注意,整個圖像比輸入圖像更清晰。

1.3 素描濾波器

此過濾器生成的輸出看起來像鉛筆草圖。有兩個輸出,一個是將濾鏡應用於彩色輸入圖像的結果,另一個是將其應用於輸入圖像的灰度版本的結果。坦率地說,我對這個過濾器印象不深,因爲結果看起來不太棒。調用如下:

C++:

pencilSketch(Mat src, Mat dst_gray, Mat dst_color, float sigma_s=60, float sigma_r=0.07f, float shade_factor=0.02f)

Python:

dst_gray, dst_color = cv2.pencilSketch(src, sigma_s=60, sigma_r=0.07, shade_factor=0.05)

參數與邊緣增強濾鏡相同。shade_factor(範圍0到0.1)是輸出圖像強度的簡單縮放。值越高,結果越亮。

將pencilSketch濾鏡應用於輸入圖像的結果如下所示。

1.4 風格化濾波器

風格化過濾器產生的輸出看起來像使用水彩繪製的圖像。調用函數如下:

C++:

stylization(Mat src, Mat dst, float sigma_s=60, float sigma_r=0.45f)

Python:

dst = cv2.stylization(src, sigma_s=60, sigma_r=0.07)

參數與邊緣增強濾鏡相同。應用於輸入圖像的結果如下所示。

2 代碼

所有代碼見:

https://github.com/luohenyueji/OpenCV-Practical-Exercise

C++:

#include "pch.h"
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
	// Read image 讀取圖像
	Mat im = imread("./image/cow.jpg");
	Mat imout, imout_gray;

	// Edge preserving filter with two different flags. 保邊濾波器
	edgePreservingFilter(im, imout, RECURS_FILTER);
	imwrite("edge-preserving-recursive-filter.jpg", imout);

	edgePreservingFilter(im, imout, NORMCONV_FILTER);
	imwrite("edge-preserving-normalized-convolution-filter.jpg", imout);

	// Detail enhance filter 邊緣增強濾波器
	detailEnhance(im, imout);
	imwrite("detail-enhance.jpg", imout);

	// Pencil sketch filter 素描濾波器
	pencilSketch(im, imout_gray, imout);
	imwrite("pencil-sketch.jpg", imout_gray);
	imwrite("pencil-sketch-color.jpg", imout_gray);

	// Stylization filter 風格化濾波器
	stylization(im, imout);
	imwrite("stylization.jpg", imout);

	return 0;
}

Python:

import cv2

# Read image
im = cv2.imread("./image/cow.jpg");

# Edge preserving filter with two different flags.
imout = cv2.edgePreservingFilter(im, flags=cv2.RECURS_FILTER);
cv2.imwrite("edge-preserving-recursive-filter.jpg", imout);

imout = cv2.edgePreservingFilter(im, flags=cv2.NORMCONV_FILTER);
cv2.imwrite("edge-preserving-normalized-convolution-filter.jpg", imout);

# Detail enhance filter
imout = cv2.detailEnhance(im);
cv2.imwrite("detail-enhance.jpg", imout);

# Pencil sketch filter
imout_gray, imout = cv2.pencilSketch(im, sigma_s=60, sigma_r=0.07, shade_factor=0.05);
cv2.imwrite("pencil-sketch.jpg", imout_gray);
cv2.imwrite("pencil-sketch-color.jpg", imout);

# Stylization filter
cv2.stylization(im,imout);
cv2.imwrite("stylization.jpg", imout);

3 參考

https://www.learnopencv.com/non-photorealistic-rendering-using-opencv-python-c/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章