이 글은 주로 이미지의 이진화, 즉 그레이스케일을 기반으로 한 임계값 분할에 중점을 둡니다. 이진화 방법에는 여러 가지가 있습니다. 실제로 이미지 처리 중에 대상 영역을 완벽하게 분할할 수 있다면 절반 이상의 성공이 달성된다는 점은 이진화의 중요성을 보여줍니다. 이 글에서는 주로 세 가지 이진화 방법을 소개합니다.
1. 임계값 고정 방법으로 임계값을 설정하고 임계값보다 큰 픽셀을 255로 설정합니다. 그렇지 않으면 0입니다. 이는 가장 간단하고 가장 불안정한 효과입니다.
<span style="font-size:14px;"><span style="font-size:10px;">public void SimBinary(){ toGray();//灰度化 int Threshold = 128; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { if(data[x + y * w] < Threshold){ data[x + y * w] = 0; }else{ data[x + y * w] = 255; } } } }</span></span>
연산 효과는 다음과 같습니다.
2. 루프 방식(참고: 공통 바이너리 값 이미지 처리 방법 요약)
1. 초기화 임계값 T는 직접 설정하거나 임의의 방법을 기반으로 생성할 수 있습니다.
2. 임계값 맵에 따라 각 픽셀 데이터 P(n,m)는 객체 픽셀 데이터 G1과 배경 픽셀 데이터 G2로 구분됩니다. (n은
행, m은 열)
3. G1의 평균은 m1, G2의 평균은 m2
4. (m1 + m2)/2
5. 두 번째 단계로 돌아가서 새 임계값을 사용하여 계속해서 픽셀 데이터를 객체와 베이징 픽셀 데이터로 나누고, 2~4단계를 계속합니다.
계산된 새 임계값이 이전 임계값과 같을 때까지.
코드는 다음과 같습니다.
<span style="font-size:14px;"> public void IterBinary(){ toGray(); int Threshold = 128; int preThreshold = 256; while (Math.abs(Threshold-preThreshold) > 4){ int s1 = 0; int s2 = 0; int f1 = 0; int f2 = 0; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { if(data[x + y * w] < Threshold){ s1 += data[x + y * w]; f1++; }else{ s2 += data[x + y * w]; f2++; } } } preThreshold = Threshold; Threshold = (int)((s1/f1+s2/f2)/2); } for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { if(data[x + y * w] < Threshold){ data[x + y * w] = 0; }else{ data[x + y * w] = 255; } } } }</span>
효과는 다음과 같습니다.
3. 적응형 임계값 알고리즘(Otsu Threshold method))
최대 클래스 간 분산 방법은 1979년 일본 학자 Otsu가 제안한 적응형 임계값 결정 방법으로 Otsu 방법, 줄여서 OTSU라고도 합니다. 이미지의 회색조 특성에 따라 이미지를 배경과 대상의 두 부분으로 나눕니다. 배경과 대상 간의 클래스 간 차이가 클수록 이미지를 구성하는 두 부분의 차이가 커집니다. 대상의 일부를 배경으로 잘못 분류하거나 배경의 일부를 대상으로 잘못 분류한 경우 두 부분의 차이는 작아질 것입니다. 따라서 클래스 간의 분산을 최대화하는 분할은 오분류 가능성이 가장 작은 것을 의미합니다. 이미지 I(x, y)의 경우 전경(즉, 대상)과 배경의 분할 임계값을 T로 표시하고 전체 이미지에서 전경에 속하는 픽셀 수의 비율을 Ω0으로 표시하며 평균 회색 레벨 μ0; 전체 이미지에 대한 배경 픽셀 수를 표시합니다. 이미지의 스케일은 Ω1이고 평균 회색 레벨은 μ1입니다. 영상의 전체 평균
회색조를 μ로 표시하고 클래스 간 분산을 g로 표시합니다. 영상의 배경이 어둡고 영상의 크기가 M×N이라고 가정하면, 영상에서 계조값이 임계값 T보다 작은 픽셀 수는 N0으로 기록되고, 회색 값이 임계값 T보다 큰 경우 N1으로 기록됩니다.
Ω0=N0/ M×N (1)
Ω1=N1/ M×N (2)
N0+N1=M×N(3)
Ω0+Ω1=1(4)
μ=Ω0*μ0+Ω1*μ1(5)
g=Ω0(μ0-μ)^2+Ω1( μ1-μ)^2 (6)
방정식 (5)를 방정식 (6)에 대입하면 등가 공식이 얻어집니다.
g=Ω0Ω1(μ0-μ1)^2 (7)
원하는 클래스 간 분산을 최대화하는 임계값 T를 얻기 위해 순회 방법을 사용합니다.
코드는 다음과 같습니다.
<span style="font-size:14px;">public void Otsu(){ toGray(); int num = h*w; int[] hist = hist(); int sum = math.sum(hist); double[] res = new double[256]; double m1=0,m2=0,w1=0,w2=0; for(int k=0;k<256;k++){ for(int i=0;i<k;i++){ m1 +=hist[i]; } w1 = m1/num; w2 = 1-w1; m2 = (sum-m1)/(255-k); m1 = m1/(k+1); res[k] = w1*w2*Math.abs(m1 - m2)*Math.abs(m1 - m2); } int Threshold = math.maxIndex(res); //获得最大值的下标 for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { if(data[x + y * w] < Threshold){ data[x + y * w] = 0; }else{ data[x + y * w] = 255; } } } }</span>
실행 효과는 다음과 같습니다.
위는 Java의 이진화입니다. 이미지 및 Otsu 임계값 방법 콘텐츠, 더 많은 관련 콘텐츠를 보려면 PHP 중국어 웹사이트(www.php.cn)에 주목하세요!