Delphi画像処理--中値フィルタリング
ヒントを読む:
「Delphi画像処理」シリーズは効率に重点を置き、一般コードはPASCAL、コアコードはBASMを採用している.
「C++画像処理」シリーズはコードがはっきりしていて、可読性が主で、すべてC++コードを使用しています.
できるだけ両者の内容を一致させ、互いに対照することができる.
本明細書のコードは、文書「Delphi画像処理--データ型および共通プロセス」のImageDataを含む必要がある.pasユニット.
画像の中値フィルタリングとは、ある画素を中心としたn次画素マトリクスにおいて、その画素のRGB値の代わりにR、G、Bの各成分の中間値を探し出し、画像ノイズフィルタリングの目的を達成することである.ここでの中間値は、画素マトリクスR,G,Bの各成分の算術平均値ではなく、画素マトリクスR,G,Bの各成分を並べ替えた中位値である.
以下はDelphi画像における値フィルタリングの実装コードである.
中値フィルタリングは、各画素に対してn次マトリクスソート法を用いてR、G、B成分の中間値を探し出すため、非常に時間がかかる.最大の消費時間は主にソートプロセスであり、本論文の中値フィルタリングプロセスはBASMコードを使用したが、このフィルタリングプロセスはまだ遅い.明らかにソートアルゴリズムは操作速度を高める鍵であり、私は多種のソートアルゴリズムを試験したが、理想的ではなく、仕方がなく、最もよく使われる3次中値フィルタリングソートを改善するしかなかった.本論文では、中値フィルタリングプロセスで画像を処理する3次中値フィルタリング速度は相対的に速い.半径が1より大きい(すなわち3*3以上の)中値フィルタソートについては、挿入ソートに変更し、中値より小さいデータだけを比較し、中値以上のデータは直接無視します.私たちはただの中間値が必要なので、中間値より大きいデータソートには時間の無駄に違いありません.これにより、処理時間が以前より平均20%節約されました.しかし、やはり時間がかかります.
「Delphi画像処理」シリーズはGDI+ユニットを使用してアドレスをダウンロードし、説明は文章「GDI+for VCL基礎--GDI+とVCL」を参照してください.
レベルが限られているため、間違いは避けられないので、指摘と指導を歓迎します.メールアドレス:[email protected]
ここでは『Delphi画像処理--記事インデックス』にアクセスできます.
「Delphi画像処理」シリーズは効率に重点を置き、一般コードはPASCAL、コアコードはBASMを採用している.
「C++画像処理」シリーズはコードがはっきりしていて、可読性が主で、すべてC++コードを使用しています.
できるだけ両者の内容を一致させ、互いに対照することができる.
本明細書のコードは、文書「Delphi画像処理--データ型および共通プロセス」のImageDataを含む必要がある.pasユニット.
画像の中値フィルタリングとは、ある画素を中心としたn次画素マトリクスにおいて、その画素のRGB値の代わりにR、G、Bの各成分の中間値を探し出し、画像ノイズフィルタリングの目的を達成することである.ここでの中間値は、画素マトリクスR,G,Bの各成分の算術平均値ではなく、画素マトリクスR,G,Bの各成分を並べ替えた中位値である.
以下はDelphi画像における値フィルタリングの実装コードである.
procedure MedianValues(var Dest: TImageData; const Source: TImageData;
buf: Pointer; SortSize, Size, MatrixOffset: Integer);
var
width, height: Integer;
dstOffset, srcOffset: Integer;
median: Pointer;
procedure MedianSort;
asm
mov edx, edi // i = count - 1
mov al, [esi] // al = r(gb)
@@Loop: // while (i >= 0 && buf[i].r(rb) > al) i --;
sub edx, 4
js @@1
cmp al, [ebx+edx]
jb @@Loop
@@1:
add edx, 4 // i ++
mov ecx, edi //
@@moveLoop:
cmp ecx, edx // memmove(buf[i], buf[i+1], count - i)
je @@2
mov ah, [ebx+ecx-4]
mov [ebx+ecx], ah
sub ecx, 4
jmp @@moveLoop
@@2:
mov [ebx+edx], al // buf[i] = al
inc ebx
inc esi
end;
asm
push esi
push edi
push ebx
push ecx
call _SetCopyRegs
mov width, ecx
mov height, edx
mov dstOffset, ebx
mov srcOffset, eax
pop ebx
mov eax, ebx
add eax, SortSize
sub eax, 4
mov median, eax
@@yLoop:
push width
@@xLoop:
push esi
push edi
xor edi, edi
mov ecx, Size
@@iLoop:
push ecx
mov ecx, Size
@@jLoop:
push ecx
call MedianSort
call MedianSort
call MedianSort
inc esi
sub ebx, 3
cmp edi, SortSize
je @@1
add edi, 4
@@1:
pop ecx
loop @@jLoop
add esi, MatrixOffset
pop ecx
loop @@iLoop
pop edi
pop esi
mov eax, median
mov eax, [eax]
mov cl, [edi].TARGBQuad.Alpha
mov [edi], eax
mov [edi].TARGBQuad.Alpha, cl
add esi, 4
add edi, 4
dec width
jnz @@xLoop
add esi, srcOffset
add edi, dstOffset
pop width
dec height
jnz @@yLoop
pop ebx
pop edi
pop esi
end;
procedure MedianValues3(var Dest: TImageData; const Source: TImageData; buf: Pointer; MatrixOffset: Integer);
var
width, height: Integer;
dstOffset, srcOffset: Integer;
median: Pointer;
procedure AssortValue;
asm
mov ah, [esi]
mov dl, [esi+4]
mov al, [esi+8]
cmp ah, al
jae @@1
xchg ah, al
@@1:
cmp ah, dl
jae @@2
xchg ah, dl
@@2:
cmp al, dl
jbe @@3
xchg al, dl
@@3:
mov [ebx], ah // ah = large
mov [ebx+4], dl // dl = center
mov [ebx+8], al // al = small
inc esi
inc ebx
end;
procedure GetValue;
asm
mov ah, [ebx] // large group: ebx ebx+12 ebx+24
mov dl, [ebx+4] // center group: ebx+4 ebx+16 ebx+28
mov al, [ebx+8] // small group: ebx+8 ebx+20 ebx+32
mov dh, [ebx+16]
cmp ah, [ebx+12] // ah = min of large group
jbe @@1
mov ah, [ebx+12]
@@1:
cmp ah, [ebx+24]
jbe @@2
mov ah, [ebx+24]
@@2:
cmp dh, dl
jae @@3
xchg dh, dl
@@3:
cmp dh, [ebx+28]
jae @@4
xchg dh, [ebx+28]
@@4:
cmp dl, [ebx+28] // dl = median of center group
jae @@5
mov dl, [ebx+28]
@@5:
cmp al, [ebx+20] // al = max of small group
jae @@6
mov al, [ebx+20]
@@6:
cmp al, [ebx+32]
jae @@7
mov al, [ebx+32]
@@7:
cmp ah, al
jae @@8
xchg al, ah
@@8:
cmp ah, dl
jae @@9
xchg ah, dl
@@9:
cmp al, dl // al = median of [ah, dl, al]
jae @@10
mov al, dl
@@10:
mov [edi], al
inc edi
inc ebx
end;
asm
push esi
push edi
push ebx
push ecx
call _SetCopyRegs
mov width, ecx
mov height, edx
mov dstOffset, ebx
mov srcOffset, eax
add MatrixOffset, 9
pop ebx
@@yLoop:
push width
@@xLoop:
push esi
push ebx
mov ecx, 3
@@mLoop:
call AssortValue
call AssortValue
call AssortValue
add ebx, 9
add esi, MatrixOffset
loop @@mLoop
pop ebx
pop esi
call GetValue
call GetValue
call GetValue
add esi, 4
sub ebx, 3
inc edi
dec width
jnz @@xLoop
add esi, srcOffset
add edi, dstOffset
pop width
dec height
jnz @@yLoop
pop ebx
pop edi
pop esi
end;
procedure ImageMedianValues(var Data: TImageData; Radius: Integer);
var
exp: TImageData;
Buf: array of Byte;
Size, SortSize: Integer;
MatrixOffset: Integer;
begin
Size := (Radius shl 1) + 1;
exp := _GetExpandData(Data, Radius);
MatrixOffset := exp.Stride - (Size shl 2);
try
if Radius = 1 then
begin
SetLength(Buf, 9 * Sizeof(TARGBQuad));
MedianValues3(Data, exp, Buf, MatrixOffset);
end
else
begin
SortSize := ((Size * Size + 1) shr 1) * Sizeof(TARGBQuad);
SetLength(Buf, SortSize + Sizeof(TARGBQuad));
MedianValues(Data, exp, Buf, SortSize, Size, MatrixOffset);
end;
finally
FreeImageData(exp);
end;
end;
中値フィルタリングは、各画素に対してn次マトリクスソート法を用いてR、G、B成分の中間値を探し出すため、非常に時間がかかる.最大の消費時間は主にソートプロセスであり、本論文の中値フィルタリングプロセスはBASMコードを使用したが、このフィルタリングプロセスはまだ遅い.明らかにソートアルゴリズムは操作速度を高める鍵であり、私は多種のソートアルゴリズムを試験したが、理想的ではなく、仕方がなく、最もよく使われる3次中値フィルタリングソートを改善するしかなかった.本論文では、中値フィルタリングプロセスで画像を処理する3次中値フィルタリング速度は相対的に速い.半径が1より大きい(すなわち3*3以上の)中値フィルタソートについては、挿入ソートに変更し、中値より小さいデータだけを比較し、中値以上のデータは直接無視します.私たちはただの中間値が必要なので、中間値より大きいデータソートには時間の無駄に違いありません.これにより、処理時間が以前より平均20%節約されました.しかし、やはり時間がかかります.
「Delphi画像処理」シリーズはGDI+ユニットを使用してアドレスをダウンロードし、説明は文章「GDI+for VCL基礎--GDI+とVCL」を参照してください.
レベルが限られているため、間違いは避けられないので、指摘と指導を歓迎します.メールアドレス:[email protected]
ここでは『Delphi画像処理--記事インデックス』にアクセスできます.