Processing의 바이라 테럴 필터
18758 단어 processing이미지 처리CreativeCoding
오늘은 Metal이 아닌 Processing입니다.
바이라터럴 필터
이번 기사에서는 왼쪽 사진과 같은 비 포토 리얼리스틱한 화상 처리를 하고 싶습니다.
「바이라테랄 필터란 무엇인가」라고 하는 것에 관해서는, 참고에 실려 있습니다만, 가우시안 필터와 바이라터럴 필터 라는 페이지에 자세히 설명되어 있습니다. 가우시안 필터를 발전시킨 필터로 간단하지만 효과적인 화상 처리 필터입니다.
구현할 수식
보기 힘든 수식이지만 갑자기 갑니다.
우선, 필터의 크기는 $5\times5$로 합니다.
BF(i,j) = \frac{\sum_{n=-2}^2 \sum_{m=-2}^2 exp\bigl(-\alpha (n^2+m^2)\bigr)exp\Bigl(-\beta\bigl(f(i,j)-f(i+n, j+m)\bigr)^2\Bigr)f(i+n,j+m)}{\sum_{n=-2}^2 \sum_{m=-2}^2 exp\bigl(-\alpha (n^2+m^2)\bigr)exp\bigl(-\beta(f(i,j)-f(i+n, j+m))^2\bigr)}
\\
= \frac{\sum_{n=-2}^2 \sum_{m=-2}^2 exp\bigl(-\alpha \text{フィルタの中心からの距離}\bigr)exp\Bigl(-\beta\text{色の差分}\Bigr)f(i+n,j+m)}{\sum_{n=-2}^2 \sum_{m=-2}^2 exp\bigl(-\alpha \text{フィルタの中心からの距離}\bigr)exp\bigl(-\beta\text{色の差分}\bigr)}
\\
= \frac{\bigl(\text{セルの重み}\times\text{セルの画素値}\bigr)の和}{\text{セルの重みの和}}
$ BF (i, j) $는 이미지 : $ f $의 $ i, j $에 바이 라터럴 필터를 걸었을 때의 출력 화소 값으로 합니다.
조금 긴 수식으로 무서워 보이지만 조금 견디자! 잘 살펴보면 분모와 분자가 거의 같은 것을 알 수 있습니다.
생각보다 쉽게 해명하는 것이 빠르다고 합니다.
일단, 이 수식의 요소를 전부 해명해 가고 싶습니다.
변수 n, m
$\sum $에서 사용되는 변수입니다.
n은 x 축 방향, m은 y 축 방향의 필터 내의 중심으로부터의 변위입니다.
파라미터 α와 β
BF(i,j) = \frac{\sum_{n=-2}^2 \sum_{m=-2}^2 exp\bigl(-\alpha (n^2+m^2)\bigr)exp\Bigl(-\beta\bigl(f(i,j)-f(i+n, j+m)\bigr)^2\Bigr)f(i+n,j+m)}{\sum_{n=-2}^2 \sum_{m=-2}^2 exp\bigl(-\alpha (n^2+m^2)\bigr)exp\bigl(-\beta(f(i,j)-f(i+n, j+m))^2\bigr)}
\\
= \frac{\sum_{n=-2}^2 \sum_{m=-2}^2 exp\bigl(-\alpha \text{フィルタの中心からの距離}\bigr)exp\Bigl(-\beta\text{色の差分}\Bigr)f(i+n,j+m)}{\sum_{n=-2}^2 \sum_{m=-2}^2 exp\bigl(-\alpha \text{フィルタの中心からの距離}\bigr)exp\bigl(-\beta\text{色の差分}\bigr)}
\\
= \frac{\bigl(\text{セルの重み}\times\text{セルの画素値}\bigr)の和}{\text{セルの重みの和}}
각각 값이 클수록 영향을받지 않는 이유는 $exp$의 지수에 $\text{마이너스}$가 포함되어 있기 때문입니다.
공간 필터란?
그런데, 「필터의 중심으로부터의 거리」라든지 「대상의 픽셀」이라고 하는 것은 어떤 것일까요. 이것을 이해하기 위해서는 먼저 공간 필터라는 것을 이해합시다. 공간 필터란, 「대상이 되는 픽셀 주위의 픽셀도 이용해 처리를 실시하는 필터」를 말합니다.
공간 필터는 이러한 형태를 하고 있어, 한가운데에 대상 픽셀이 옵니다.
화상 처리란, 가공하고 싶은 화상의 「각 픽셀에 처리를 실시한다」를 의미합니다. 그러므로 통상 화상 처리를 실시할 때는, 그 가공하고 싶은 화상의 화소 수분만큼, 같은 처리가 실행되고 있습니다. 그러므로, 다중의 for문이나 $\sum$가 잘 나오고, 초학자를 혼란시켜 버립니다. 이 기사 내에서는 「지금 처리하고 싶은 각 픽셀」을 「대상 픽셀」이라고 부릅니다. $f$를 가공하고 싶은 화상(입력 화상)으로서, $f(i, j)$는 화상상의 $(i, j)$의 픽셀의 정보를 나타냅니다. 이미지 자체는 수식에 의한 함수는 아니지만, 처리 필터를 수식으로 표현하기 위해서도. $(i,j)$라는 좌표를 건네주면, 그 좌표의 픽셀 데이터가 돌아오는 함수 $f$라고 해석하고 있습니다. 코드에서 color pix_ij = pixels[j*width+i]; 로 주면 된다. 공간은 영역을 말하며, 그 영역의 중심에 대상 픽셀이 오도록 공간 필터를 설정합니다. 기본적으로 필터의 중심에 대상 픽셀이 오도록 필터를 배치하고 그것을 모든 픽셀에 대해 필터링합니다. 필터의 각 셀에 \text{각 셀의 가중치}\times\text{각 셀의 픽셀 값} 를 계산하고 있습니다. 이것은 분자의 $ \ sum $의 내용입니다. Σ와 for 문 수식의 $\sum$는 어떤 의도로 사용되고 있는지 생각하지 않아도 일단 프로그램에 떨어뜨릴 수 있습니다. $\sum_{i=0}^9$는 for(int i=0; i<10; i++) { ~ }이 되고, $\sum_{i=a}-b$는 for(int i=a; i<=b; i++) { = } 로 하면 프로그램으로 바꿀 수 있습니다. 그리고 이 { ~~ } 에 $\sum$ 의 내용을 써 주면 됩니다. 수식을 읽는다. 이번 바이라터럴 필터에서는 \text{ 각 픽셀의 가중치} = exp\bigl(-\alpha (n^2+m^2)\bigr)exp\Bigl(-\beta\bigl(f(i,j)-f(i+n) , j+m)\bigr)^2\Bigr) 그리고 식의 대부분이이 픽셀의 가중치에 사용되고있는 것을 알 수 있습니다. (보다는 필터는 가중치 배열이므로 당연하지만 ...) BF(i,j) = \frac{\sum_{n=-2}^2 \sum_{m=-2}^2 \text{가중}\times f(i+n,j+m)}{\ sum_{n=-2}^2 \sum_{m=-2}^2 \text{가중}} \\ 그리고이 픽셀의 가중치는 exp로 만들어집니다. 그리고 $exp\bigl(-\alpha (n^2+m^2)\bigr)$ 와 $exp\Bigl(-\beta\bigl(f(i,j)-f(i+n, j+) m)\bigr)^2\Bigr)$ 중 어느 것에 대해서도, $-\alpha (n^2+m^2) \le 0$ $-\beta\bigl(f(i,j)-f(i+n, j+m)\bigr)^2 \le 0$ 따라서 $(n^2+m^2)$ 또는 $\bigl(f(i,j)-f(i+n, j+m)\bigr)^2$가 커질수록 셀의 가중치가 작다는 것을 알 수 있습니다. $ n ^ 2 + m ^ 2 $는 필터의 중심으로부터의 거리를 나타냅니다. $\bigl(f(i,j)-f(i+n, j+m)\bigr)^2$ 는 필터 내의 중심의 화소값과의 화소차를 나타내고 있습니다.
가우스 함수
첫째, 바이 라터럴 필터는 가우시안 필터의 응용이라고 설명했습니다. 그러므로, 가우스 함수를 사용하고 있습니다만, 계수 등을 제거해 버리고, 단지 $exp$함수를 사용하고 있습니다.
구현하다
이 바이 라터럴 필터를 이미지의 RGB 성분 각각에 적용합니다.
구문 하이라이트 때문에 확장자는 pde → java로 변경
bilateral.java
// parameters
final float A = 0.001;
final float B = 0.01;
final int W = 10;
// resource
PImage koara;
color[] k_pixs;
color[] koara_bilateral;
int w, h;
void settings() {
koara = loadImage("koara.jpg");
w = koara.width;
h = koara.height;
size(w*2, h);
k_pixs = koara.pixels;
koara_bilateral = new color[w*h];
for (int i=0; i<h*w; i++) { koara_bilateral[i]=color(100); }
}
void setup() {
}
void draw() {
for (int y=W; y<h-W; y++) {
for (int x=W; x<w-W; x++) {
color c = bilateral(x, y);
koara_bilateral[y*w+x] = c;
set(x, y, koara_bilateral[y*w+x]);
}
}
image(koara, w, 0);
// 多重にかけるために,繰越処理をする.
k_pixs=koara_bilateral.clone();
}
color bilateral(int i, int j) {
float sum_r = 0.0;
float W_3_r = 0.0;
float sum_g = 0.0;
float W_3_g = 0.0;
float sum_b = 0.0;
float W_3_b = 0.0;
for (int n=-W; n<=W; n++) {
for (int m=-W; m<=W; m++) {
color c_ij = k_pixs[i+j*w];
color c_nm = k_pixs[(i+n)+(j+m)*w];
sum_r += gauss(n*n+m*m, pow(red(c_ij)-red(c_nm), 2), A, B)*red(c_nm);
W_3_r += gauss(n*n+m*m, pow(red(c_ij)-red(c_nm), 2), A, B);
sum_g += gauss(n*n+m*m, pow(green(c_ij)-green(c_nm), 2), A, B)*green(c_nm);
W_3_g += gauss(n*n+m*m, pow(green(c_ij)-green(c_nm), 2), A,B);
sum_b += gauss(n*n+m*m, pow(blue(c_ij)-blue(c_nm), 2), A,B)*blue(c_nm);
W_3_b += gauss(n*n+m*m, pow(blue(c_ij)-blue(c_nm), 2), A, B);
}
}
return color(sum_r/W_3_r, sum_g/W_3_g, sum_b/W_3_b);
}
float gauss(float x, float y, float a, float b) {
return exp(-a*x-b*y);
}
바이 라터럴 필터를 여러 번 걸어 보았을 때의 천이 이미지입니다.
왼쪽 상단은 한 번이고 오른쪽 하단은 6 번입니다.
대부분 일러스트 톤의 이미지가되어있는 것을 알 수 있습니다.
참고
가우시안 필터와 바이라터럴 필터
Reference
이 문제에 관하여(Processing의 바이라 테럴 필터), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/micky_dtl/items/9a5e1c3fb0e8b1be5fd9
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여(Processing의 바이라 테럴 필터), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/micky_dtl/items/9a5e1c3fb0e8b1be5fd9텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)