Các thuật toán tốt nhất cho ngưỡng ảnh tài liệu trong ví dụ này là gì?


31

Tôi đang cố gắng thực hiện các thuật toán nhị phân khác nhau cho hình ảnh được hiển thị: nhập mô tả hình ảnh ở đây

Đây là mã:

clc;
clear;
x=imread('n2.jpg');     %load original image

Bây giờ chúng tôi thay đổi kích thước hình ảnh để công việc tính toán trở nên dễ dàng hơn về sau đối với chúng tôi.

size(x);
x=imresize(x,[500 800]);
figure;
imshow(x);
title('original image');

z=rgb2hsv(x);       %extract the value part of hsv plane
v=z(:,:,3);
v=imadjust(v);

% bây giờ chúng tôi tìm thấy độ lệch trung bình và độ lệch chuẩn cần thiết cho thuật toán niblack và% sauvola

m = mean(v(:))
s=std(v(:))
k=-.4;
value=m+ k*s;
temp=v;

% thực hiện thuật toán ngưỡng niblack:

for p=1:1:500
    for q=1:1:800
        pixel=temp(p,q);
        if(pixel>value)
            temp(p,q)=1;
        else
            temp(p,q)=0;
        end
    end
end
figure;
imshow(temp);
title('result by niblack');
k=kittlerMet(g);
figure;
imshow(k);
title('result by kittlerMet');

% thực hiện thuật toán ngưỡng sauvola:

val2=m*(1+.1*((s/128)-1));
t2=v;
for p=1:1:500
for q=1:1:800
    pixel=t2(p,q);
    if(pixel>value)
        t2(p,q)=1;
    else
        t2(p,q)=0;
    end
end

kết thúc

figure;
imshow(t2);
title('result by sauvola');

Kết quả tôi thu được là như sau: nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Như bạn có thể thấy hình ảnh kết quả bị suy giảm tại các điểm tối hơn. Có ai đó vui lòng đề xuất cách tối ưu hóa kết quả của tôi không ??


1
Bạn có thể sử dụng thông tin màu sắc để loại bỏ nền thay vì chỉ độ sáng?
endolith

Kính trọng Ngài / thưa bà. Tôi đang thực hiện dự án xử lý hình ảnh. Tôi là một khái niệm nhị phân thú vị .. vui lòng kiểm tra và sửa mã hóa ... Tôi lấy mã hóa và chạy chương trình. Nhưng một số lỗi xảy ra mã hóa này ... Hàm không xác định hoặc biến 'g'. và một lỗi khác là Lỗi trong msp (dòng 31) k = kittlerMet (g); .. Cách giải quyết ... Vui lòng sửa mã hóa ...
muthu

Câu trả lời:


49

Hình ảnh của bạn không có độ sáng đồng đều, vì vậy bạn không nên làm việc với ngưỡng đồng nhất. Bạn cần một ngưỡng thích ứng. Điều này có thể được thực hiện bằng cách xử lý trước hình ảnh để làm cho độ sáng đồng đều hơn trên hình ảnh (mã được viết bằng Mathicala, bạn sẽ phải tự thực hiện phiên bản Matlab):

Một cách đơn giản để làm cho đồng nhất độ sáng là xóa văn bản thực tế khỏi hình ảnh bằng bộ lọc đóng:

white = Closing[src, DiskMatrix[5]]

nhập mô tả hình ảnh ở đây

Kích thước bộ lọc nên được chọn lớn hơn chiều rộng hành trình phông chữ và nhỏ hơn kích thước của các vết bẩn bạn đang cố gắng loại bỏ.

EDIT: Tôi đã được yêu cầu trong các ý kiến ​​để giải thích những gì một hoạt động đóng làm. Đó là một sự giãn nở hình thái theo sau là một sự xói mòn hình thái . Sự giãn nở về cơ bản di chuyển phần tử cấu trúc ở mọi vị trí trong ảnh và chọn pixel sáng nhất dưới mặt nạ, do đó:

  • loại bỏ các cấu trúc tối nhỏ hơn thành phần cấu trúc
  • thu nhỏ các cấu trúc tối lớn hơn bằng kích thước của phần tử cấu trúc
  • mở rộng cấu trúc sáng

Hoạt động xói mòn làm ngược lại (nó chọn pixel tối nhất bên dưới phần tử cấu trúc), vì vậy nếu bạn áp dụng nó trên hình ảnh bị giãn:

  • các cấu trúc tối đã bị xóa vì chúng nhỏ hơn thành phần cấu trúc vẫn không còn
  • các cấu trúc tối hơn được thu nhỏ lại được mở rộng trở lại kích thước ban đầu của chúng (mặc dù hình dạng của chúng sẽ mịn hơn)
  • các cấu trúc sáng được giảm xuống kích thước ban đầu của chúng

Vì vậy, thao tác đóng sẽ loại bỏ các vật tối nhỏ chỉ bằng những thay đổi nhỏ đối với vật tối lớn hơn và vật sáng.

Dưới đây là một ví dụ với các kích thước phần tử cấu trúc khác nhau:

nhập mô tả hình ảnh ở đây

Khi kích thước của phần tử cấu trúc tăng lên, ngày càng nhiều ký tự được loại bỏ. Tại bán kính = 5, tất cả các ký tự được loại bỏ. Nếu bán kính tăng hơn nữa, các vết bẩn nhỏ hơn cũng được loại bỏ:

nhập mô tả hình ảnh ở đây

Bây giờ bạn chỉ cần chia hình ảnh gốc cho "hình ảnh trắng" này để có được hình ảnh có độ sáng đồng đều (gần):

whiteAdjusted = Image[ImageData[src]/ImageData[white]*0.85]

nhập mô tả hình ảnh ở đây

Hình ảnh này bây giờ có thể được tạo thành nhị phân với ngưỡng không đổi:

Binarize[whiteAdjusted , 0.6]

nhập mô tả hình ảnh ở đây


5
Ồ Điều này thực sự mát mẻ! +1 lớn!
Phonon

@nikie +1 Rất hay - ý nghĩa chính xác của bạn khi đóng bộ lọc phải là "được chọn lớn hơn nét chữ"? Chiều rộng hay chiều dài của chữ cái nào? Hơn nữa, bộ lọc đóng 'thực sự' đang làm gì? Cảm ơn!
Spacey

1
@Mohammad: Tôi đã thêm một lời giải thích cho câu trả lời của mình. Và vâng, đây là những hoạt động phi tuyến tính. Tiêu đề phổ biến là xử lý hình ảnh.
Niki Estner

1
@nikie Đừng bận tâm, màu trắng là tối đa, không phải màu đen. :-)
Spacey

1
@gdelfino: Tôi thường cố gắng tránh nó bằng cách sử dụng mặt nạ đủ lớn và sử dụng Clip[ImageData[white],{eps,Infinity}]trong đó eps là một số nhỏ, để an toàn.
Niki Estner

6

Câu trả lời của Nikie có vẻ tốt nhất và dường như cũng đang hoạt động và tạo ra kết quả. Vì vậy, nó là một người chiến thắng rõ ràng.

Tuy nhiên, chỉ để tài liệu tôi thêm một tài liệu tham khảo, điều đó có thể rất nhanh.

Kỹ thuật này được gọi là ngưỡng thích ứng mà không yêu cầu phải tìm hiểu nền rõ ràng.

Về cơ bản, thay vì tìm ngưỡng toàn cầu phù hợp nhất - chúng ta có thể phân vùng hình ảnh trong một cửa sổ cục bộ (giả sử khoảng 7x7 hoặc phù hợp) và tìm các ngưỡng thay đổi khi cửa sổ đi qua.

Các tài liệu tham khảo dưới đây chi tiết các phương pháp chính xác. http://homepages.inf.ed.ac.uk/rbf/HIPR2/adpthrsh.htm

Phương pháp này sẽ tương đối nhanh hơn tính toán.


Không phải hai thứ đó giống nhau sao? Cụ thể là ước tính trung bình cục bộ của tín hiệu trước khi ngưỡng?
Maurits

1
@Maurits Có vẻ như sự khác biệt chính là thứ tự và số liệu thống kê được sử dụng. Ví dụ, trong các toán tử mở / đóng, (được tạo thành từ sự giãn nở và xói mòn nhưng theo một thứ tự khác), một cửa sổ được quét raster và lấy tối đa. (Trong so nhung cai khac). Tuy nhiên, trong ngưỡng thích ứng, giá trị trung bình / trung bình có thể được lấy thay vì max.
Spacey

OP đã hỏi nó trên SO là tốt, mà tôi đã trả lời. Nhưng về nguyên tắc, tôi không nghĩ có bất kỳ sự khác biệt nào giữa các câu trả lời, người ta luôn ước tính số liệu thống kê địa phương. Nếu bạn làm ngưỡng thích ứng, bạn cũng tìm hiểu nền tảng trong quy trình.
Maurits

6

Một cách khác bằng cách sử dụng bộ lọc thông dải (trong MATLAB). Chơi xung quanh với sự khác biệt của các tham số Gaussian có thể cho kết quả tốt hơn. Quá trình về cơ bản là băng thông lọc hình ảnh để loại bỏ các đốm nền tần số thấp, chuẩn hóa thành [0,1] cần thiết cho lệnh 'Graythresh', ngưỡng ảnh.

Tải hình ảnh và chuyển đổi thành thang độ xám đôi:

I = imread('hw.jpg');
I = rgb2gray(I);
I = double(I);

nhập mô tả hình ảnh ở đây

Bộ lọc sử dụng sự khác biệt của nhân Gaussian và chuẩn hóa:

J = imgaussian(I,1.5) - imgaussian(I,0.5);
J = J - min(J(:));
J = J / max(J(:));

nhập mô tả hình ảnh ở đây

Tính ngưỡng và thực hiện 010101:

T = J > graythresh(J);

nhập mô tả hình ảnh ở đây


4

Đây là một mã Matlab tốt cho ngưỡng thích ứng: http://www.mathworks.com/matlabcentral/fileexchange/8647-local-adaptive-thresholding


Argh! Yêu cầu hộp công cụ xử lý hình ảnh mặc dù. : - /
Spacey

Thật. Xin lỗi nếu bạn không có nó. Nhưng DIPImage là một Tolbox hình ảnh miễn phí cho Matlab. Diplib.org/documentation Nó có một vài phương pháp để ngưỡng (phần kiểm tra phân đoạn) và bạn cũng có thể thực hiện tất cả các hoạt động hình thái như đóng cửa. Nhà phát triển cũng có một blog cb.uu.se/~cris/blog/index.php/archives/tag/matlab
MyCarta

0

Tôi sẽ thử mã hóa này. Nhưng tôi không có câu trả lời chính xác ...

clc;
clear;
x=imread('base2.jpg');
size(x);
x=imresize(x,[500 800]);
figure;
imshow(x);
title('original image');
z=rgb2hsv(x);       %extract the value part of hsv plane
v=z(:,:,3);
v=imadjust(v);
m = mean(v(:))
s=std(v(:))
k=-2;
value=m+ k*s;
temp=v;
for p=1:1:500
    for q=1:1:800
        pixel=temp(p,q);
        if(pixel>value)
            temp(p,q)=1;
        else
            temp(p,q)=0;
        end
    end
end
figure;
imshow(temp);
title('result by niblack');
% k=kittlerMet(g);
% figure;
% imshow(k);
% title('result by kittlerMet');

val2=m*(1+.1*((s/128)-1));
t2=v;
for p=1:1:500
for q=1:1:800
    pixel=t2(p,q);
    if(pixel>value)
        t2(p,q)=1;
    else
        t2(p,q)=0;
    end
end

end
figure;
imshow(t2);
title('result by sauvola');

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây


2
Nếu điều này có nghĩa là để trả lời câu hỏi, vui lòng giải thích những gì bạn đang làm và tại sao.
Matt L.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.