https://learn.foundry.com/nuke/developers/13.2/BlinkKernels/InvertKernel.html
Introduction to Kernels — Guide to Writing Blink Kernels
Introduction to Kernels The first kernel we’re going to look at is a simple one that takes a single image as input, inverts the colours in it, multiplies them by a value and then writes them to an output image. Let’s take a closer look at it. The Inver
learn.foundry.com
InvertKernel
kernel InvertKernel : ImageComputationKernel<eComponentWise>
{
Image<eRead, eAccessPoint, eEdgeClamped> src; //the input image
Image<eWrite> dst; //the output image
param:
float multiply; //This parameter is made available to the user.
local:
float _whiteAccessPoint; //This local variable is not exposed to the user.
//In define(), parameters can be given labels and default values.
void define() {
defineParam(multiply, "Multiply", 1.0f);
}
//The init() function is run before any calls to process().
void init() {
_whiteAccessPoint = 1.0f; //Local variables can be initialised here.
}
//The process function is run at every pixel to produce the output.
void process() {
//Invert the input value from src and multiply:
dst() = (_whiteAccessPoint - src()) * multiply;
}
};
Kernels and Iteration
Blink 커널의 개요
Blink에서 커널을 선언하는 방식은 C++의 클래스를 정의하는 방식과 유사합니다. 아래는 Blink 커널을 선언하는 예입니다.
kernel InvertKernel : ImageComputationKernel<eComponentWise>
주요 요소:
- 커널 타입 (kernel):
- InvertKernel은 Blink의 “커널”입니다. Blink 커널은 특정 작업을 수행하는 코드를 캡슐화하여, 특정 이미지 처리 작업을 수행하도록 설계된 작은 프로그램입니다.
- 상속 (ImageComputationKernel):
- InvertKernel은 ImageComputationKernel로부터 상속받습니다. 이 클래스는 출력 이미지를 생성하는 커널의 역할을 정의합니다.
- 처리 방식 (eComponentWise):
- eComponentWise는 "컴포넌트 단위"로 커널을 처리함을 의미합니다. 각 채널(예: RGB의 R, G, B)이 독립적으로 처리되며, 입력 이미지의 각 채널로부터 해당 채널만 접근할 수 있습니다.
- 반면, 픽셀 단위 처리(ePixelWise)에서는 모든 채널을 동시에 처리할 수 있으며, 채널 간 상호작용이 필요한 작업에 적합합니다.
픽셀 단위 커널의 예:
픽셀 단위 커널은 채널 간의 상호 의존성이 있는 작업(예: 채도를 조정하는 작업)에 적합합니다. 예를 들면 다음과 같습니다.
kernel SaturationKernel : ImageComputationKernel<ePixelWise>
병렬 처리
- 병렬 처리 가능성: Blink 커널은 이미지의 각 픽셀(또는 채널)을 독립적으로 처리할 수 있도록 설계되어 있어 GPU를 활용한 병렬 처리가 가능합니다.
- 실행 순서 제어 불가: ImageComputationKernel을 사용할 경우, 출력 이미지의 픽셀 또는 채널이 채워지는 순서는 제어할 수 없습니다. 따라서 각 호출은 독립적으로 실행되며, 병렬 처리가 가능한 작업에 적합합니다.
병렬 처리의 예시
InvertKernel처럼 각 출력 값을 독립적으로 계산할 수 있는 작업은 병렬 처리에 적합합니다. 많은 이미지 처리 작업들이 Blink 커널을 사용하여 이와 같은 방식으로 병렬화할 수 있습니다.
Image Specification
Blink 커널의 이미지 접근 설정
커널 본문에서는 커널이 사용하는 입력 및 출력 이미지를 지정해야 합니다. InvertKernel에서는 src라는 입력 이미지와 dst라는 출력 이미지를 사용하며, 다음과 같이 선언됩니다.
Image<eRead, eAccessPoint, eEdgeClamped> src; // 입력 이미지
Image<eWrite> dst; // 출력 이미지
각 설정의 의미
- Image<eRead, eAccessPoint, eEdgeClamped> src;:
- src는 Image 타입 객체이며, eRead를 통해 읽기 전용으로 설정되었습니다.
- eAccessPoint: 출력 공간에서 현재 위치에 있는 점에 대해서만 접근하도록 설정됩니다.
- eEdgeClamped: 이미지 외곽을 벗어난 위치에 접근 시 가장자리 픽셀 값을 반복하여 적용합니다.
- Image<eWrite> dst;:
- dst는 Image 타입 객체이며, 쓰기 전용으로 설정됩니다. 이 이미지는 반드시 출력으로 사용됩니다.
추가 설명
- 경계 처리 방법: eEdgeClamped는 이미지 경계를 벗어난 위치에 접근할 때, 가장자리를 기준으로 값을 클램핑하여 반환합니다.
- 커널 내 이미지 접근 방식: 모든 커널에는 최소한 하나의 출력 이미지(dst)가 필요하며, dst는 일반적으로 Image<eWrite> dst;와 같이 단순하게 선언됩니다.
이와 같은 설정은 Blink 커널이 메모리를 효율적으로 사용하고, 예외 상황에서 이미지 처리를 안정적으로 수행하도록 도와줍니다.
Parameters
Blink 커널의 파라미터 선언
커널의 파라미터는 param 섹션에 선언되며, 이는 C++ 클래스에서 멤버 변수를 선언하는 방식과 유사합니다. 파라미터가 없는 커널은 이 섹션을 생략할 수 있습니다.
예시: InvertKernel의 파라미터
InvertKernel은 하나의 파라미터 multiply를 가지고 있으며, 다음과 같이 선언됩니다.
param:
float multiply; // 사용자가 조정할 수 있는 파라미터
파라미터 사용 및 UI 생성
- Knob 자동 생성: 커널이 BlinkScript 노드에서 컴파일되면, 각 파라미터에 대해 조정 가능한 Knob이 자동으로 생성되어 Kernel Parameters 탭에 추가됩니다. 여기서는 Multiply 파라미터가 사용자 인터페이스로 제공됩니다.
지원되는 데이터 타입
- 기본형: float 및 int와 같은 기본 C++ 데이터 타입을 사용할 수 있습니다.
- 벡터 타입: 다차원 벡터(float2, float3, float4 등)와 매트릭스 타입(float3x3, float4x4)도 지원됩니다.
- 예: float2는 2개의 float 값을 가지는 벡터, float4x4는 4x4 매트릭스를 나타냅니다.
이와 같은 파라미터 설정으로 유연하고 다양한 이미지 처리 기능을 Blink 커널에서 구현할 수 있습니다.
Local Variables
Blink 커널의 로컬 변수 선언
커널 내부에서만 사용하는 로컬 변수는 local 섹션에 선언하며, 이는 사용자에게 노출되지 않습니다. 로컬 변수가 필요하지 않다면 local 섹션을 생략할 수 있습니다.
예시: InvertKernel의 로컬 변수
InvertKernel에는 _whitePoint라는 로컬 변수가 있습니다. 이 변수는 컬러 이미지 반전을 위해 사용되며, 입력 이미지의 white point가 1이라고 가정합니다.
local:
float _whitePoint = 1.0f; // 반전 작업에 사용되는 화이트 포인트
로컬 변수의 데이터 타입
로컬 변수는 파라미터와 유사하게 C++ 기본 타입인 float, int를 사용할 수 있으며, 다차원 벡터 타입(float2, float3, float4 등) 및 매트릭스 타입(float3x3, float4x4)도 지원됩니다.
로컬 변수 초기화
로컬 변수는 init() 함수에서 초기화할 수 있습니다. init() 함수는 병렬 처리 전에 단일 스레드에서 실행되며, process() 함수에서 병렬 처리 작업을 수행하기 전 필요한 준비 작업을 처리할 수 있습니다.
- process() 함수: 이 함수는 병렬로 여러 스레드에서 동시에 실행될 수 있습니다. process() 내에서는 로컬 변수의 읽기 전용 접근이 가능하며, 각 실행 스레드는 독립적으로 임시 변수를 선언하여 사용할 수 있습니다.
요약
- local 섹션은 로컬 변수 선언을 위한 곳입니다.
- init() 함수에서 초기화하며, 병렬 처리 전 작업을 수행합니다.
- process() 함수에서는 로컬 변수에 읽기 전용 접근을 제공하고, 병렬 실행 시 각 스레드가 독립적인 임시 변수를 선언하여 사용할 수 있습니다.
The define() Function
파라미터를 설정하려면 define 함수에서 defineParam() 호출을 통해 설정할 수 있습니다. defineParam 함수는 세 개의 인자를 받는데, 이는 파라미터의 이름, 사용자에게 표시될 파라미터 이름(문자열 형식), 그리고 파라미터의 기본값입니다. 예를 들어, 아래 코드는 multiply 파라미터에 사용자에게 "Multiply"로 표시될 이름과 기본값 1.0을 지정합니다.
void define() {
defineParam(multiply, "Multiply", 1.0f);
}
define 함수는 커널에 파라미터가 있을 경우, 사용자에게 표시될 이름과 기본값을 지정하는 것이 좋습니다. 만약 커널에 파라미터가 없다면 define 함수를 포함할 필요는 없습니다.
The init() Function
init() 함수 설명
init() 함수는 이미지 처리 작업이 시작되기 전에 한 번 호출되는 함수로, 필요한 초기화를 미리 수행하는 곳입니다. 만약 초기화가 필요 없다면 init() 함수를 생략할 수 있습니다.
예시: InvertKernel
다음 예시에서는 InvertKernel에서 _whitePoint 변수를 1.0으로 초기화합니다.
void init() {
_whitePoint = 1.0f; // 여기에서 로컬 변수를 초기화할 수 있습니다.
}
추가 설정 가능 항목
init() 함수에서는 변수 초기화 외에도, 입력 이미지를 처리하는 방식을 컴파일러에 지정하는 등의 설정도 가능합니다. 다음 커널 예제에서 이와 관련된 추가 예시를 확인할 수 있습니다.
The process() Function
process() 함수 설명
process() 함수는 커널에서 실제 작업이 수행되는 핵심 함수입니다. 이 함수는 픽셀 단위 커널에서는 각 출력 픽셀마다 한 번씩, 컴포넌트 단위 커널에서는 출력 픽셀의 각 컴포넌트마다 한 번씩 호출됩니다.
예시: InvertKernel
다음 코드에서는 InvertKernel이 입력 이미지를 반전하고, multiply 값을 곱하는 작업을 수행합니다.
void process() {
// 입력 값(src)을 반전시키고 multiply 값을 곱하여 dst에 할당
dst() = (_whitePoint - src()) * multiply;
}
- 컴포넌트 접근 방식: InvertKernel은 컴포넌트 단위 커널로, 각 출력 컴포넌트는 입력 이미지의 대응되는 컴포넌트만 접근할 수 있습니다.
- dst()는 현재 픽셀의 출력 이미지의 현재 컴포넌트를, src()는 현재 픽셀의 입력 이미지의 현재 컴포넌트를 접근합니다.
- 읽기/쓰기 접근 지정자:
- src는 eRead 접근 지정자로 설정되어 읽기 전용입니다.
- dst는 eWrite로 설정되어 쓰기 전용입니다. 또한 **eReadWrite*로 설정하면 이미지에 대한 읽기와 쓰기 모두 가능하게 됩니다.
작업 방식 변경 예시
process 함수의 내용을 수정하면 커널의 작업 방식을 변경할 수 있습니다. 예를 들어, InvertKernel 대신 “Gain” 커널을 만들고 싶다면 _whitePoint 값을 제거하고 입력 컴포넌트에 multiply 값만 곱해주는 방식으로 코드를 수정하면 됩니다.
이 경우, 더 이상 _whitePoint 변수와 init() 함수가 필요하지 않으므로 삭제할 수 있습니다. 또한, multiply 파라미터를 gain으로 이름을 변경하고 기본값을 새로 지정하면 더 직관적인 설정이 됩니다.
'Nuke > Blink Script' 카테고리의 다른 글
blink kernels (4) (0) | 2024.12.08 |
---|---|
blink kernels (3) (0) | 2024.12.08 |
blink kernels (2) (0) | 2024.12.08 |
Blink Script (2) (1) | 2024.12.08 |
Blink Script (1) (2) | 2024.12.08 |