JPEG 포맷은 표준안이 나온지 30년이 되어가지만, 여전히 널리 사용되는 포맷이다.
심지어, 차세대 JPEG을 표방하는 코덱이 좀 나왔었는데, 다 나가떨어질 때까지 JPEG는 버티고 있다.
물론, 영상을 전문으로 하시는 분들께는 그냥 한물 간 포맷이겠지만, 현실세계에선 그렇지 않다.
JPEG는 압축률이 꽤 뛰어나다는 장점이 있지만, artifacts라 흔히 통칭되는 노이즈가 가장 큰 약점[각주:1]이다.
그리고, 나온지 오래된 포맷답게 이 artifacts를 없애는 방법들이 꽤 검토되었고, 대표적으로 다음 두 가지 방식이 있다.
가장 손쉽게 접근한 방식은 파일을 읽은 뒤에 각 픽셀을 인접 픽셀들과 비교하는 것이다.
Paint.NET의 플러그인 중 하나인 JPGNoiseReduction이 대표적이다.
대략 아래와 같은 코드[각주:2]로 설명할 수 있는데, 요지는 주변의 ±5 픽셀들과 모두 비교해서 유사한 색이면 평균을 계산하는 것.
ColorBgra color0 = src[x, y];
int count = 0;
double vR = 0;
double vG = 0;
double vB = 0;
for (int y2 = y - 5; y2 < y + 6; ++y2)
{
for (int x2 = x - 5; x2 < x + 6; ++x2)
{
ColorBgra colorT = src[x2, y2];
double yR = 0.299 * (colorT.R - color0.R);
double yG = 0.587 * (colorT.G - color0.G);
double yB = 0.114 * (colorT.B - color0.B);
if (yR * yR + yG * yG + yB * yB <= (amount * 10))
{
vR += colorT.R;
vG += colorT.G;
vB += colorT.B;
++count;
}
}
}
color0.R = (byte)(vR / count);
color0.G = (byte)(vG / count);
color0.B = (byte)(vB / count);
dst[x, y] = color0;
실제로 돌려본 결과는 아래와 같다.
우선 작업할 이미지를 하나 고른다.
항간에 떠도는 이미지를 하나 선택했다.
아무래도 artifacts를 비교하는 것이라 실사 이미지보다는 복잡한 인공 이미지가 더 적합하다.
이 이미지의 특정 영역을 4배 확대하면 아래와 같다.
복잡한 영역이라 artifacts가 눈에 크게 띈다.
이 플러그인을 적용한 결과는 아래와 같다.
지글거리는 영역이 상당부분 제거됐다는 것을 볼 수 있다.
알고리즘 자체는 그리 복잡하지 않지만, 결과는 강력하다.
JPEG의 압축 원리는 간단히 말해 이미지를 8x8 블록으로 자른 뒤 DCT 변환 후 양자화[각주:3]하는 것이다.
이 과정에서 계수를 제거함으로써 파일의 크기를 줄이는 것.
이렇게 제거된 계수를 양자화 테이블을 기반으로 복원하는 JPEG Quant Smooth라는 알고리즘이 있다.
적용 방법은 간단[각주:4]하다.
libjpeg에서 파일을 읽으면서 기존의 jpeg_start_decompress() 함수 대신 jpegqs_start_decompress() 함수를 적용하는 것.
나머지 함수들[각주:5]은 기존과 동일하게 호출하면 된다.
이 알고리즘을 기본값(iteration = 3 등)으로 적용한 결과는 아래와 같다.
위의 1번과 비교해보면 복원되는 결과가 상당히 다르다는 것을 볼 수 있다.
이 두 알고리즘은 적용되는 단계가 다르기 때문에 둘을 동시에 적용하는 것에 큰 문제는 없다.
그런데, 이러한 복원은 복원과 동시에 어떤 부분의 데이터는 손실된다는 점을 고려해야 한다.
일단 위의 이미지에 둘을 모두 적용한 결과는 아래와 같다.
이 이미지에 한정해서 생각하면, 복원 결과는 상당히 훌륭하다.
하지만, 다양한 이미지들에 놓고 테스트를 해보면 그때그때 다를 것이라 생각해야 한다.
ffmpeg으로 VirtualDub과 동일한 무압축 RGB 비디오를 만드는 법 (0) | 2021.11.10 |
---|---|
MainConcept HEVC 인코더가 2.0으로 업데이트됨 (0) | 2021.10.18 |
FFmpeg을 제대로 직접 컴파일 해보자 (3) | 2021.09.12 |
ffmpeg으로 비디오를 파이프로 넘기기 (0) | 2021.05.27 |
MainConcept HEVC 인코더 구매 삽질기 #4 (3) | 2021.05.22 |