4. Bố cục của luận án
3.2.2.2 Trích rút các cụm màu thuần nhất
Trong phần này, chúng tôi trình bày thuật toán trích rút màu và các cụm màu thuần nhất của các màu đƣợc lựa chọn, gọi là CCS. Thuật toán này của chúng tôi đã đƣợc công bố trong [46].
Đầu tiên thuật toán coi một ảnh đã cho I nhƣ một vùng. Nếu diện tích của vùng này nhỏ hơn một ngƣỡng đã cho thì thuật toán sẽ loại bỏ vùng này. Nếu vùng là thuần nhất, CCS sẽ xuất vùng này và màu của nó, và dừng. Ngƣợc lại nó gọi thủ tục Split() để phân hoạch vùng Rec thành hai vùng Rec1 và Rec2 và đẩy chúng vào Stack. Quá trình này sẽ lặp đối với mỗi vùng trong Stack cho đến khi Stack rỗng.
Thuật toán CCS có thể đƣợc viết nhƣ sau:
Trong thuật toán CCS, có các tham số minsize và tolerance. Ở đây minsize là diện tích nhỏ nhất của một vùng, tolerance chỉ ra mức nhiễu cho phép trong mỗi vùng. Nếu diện tích của một vùng nhỏ hơn minsize, vùng sẽ không đƣợc phân hoạch tiếp.
Kết quả của thuật toán này là màu và các cụm màu của nó trong một ảnh đƣợc biểu diễn bởi danh sách <(c1; rec1),(c2; rec2),...,(cn; recn)>. Ở đây ci là màu đƣợc lựa chọn, và reci là vùng có màu ci. Ký hiệu (xitl, yitl, xibr, yibr) là một hình chữ nhật với (xitl, yitl) và (xibr,yibr) là các toạ độ góc trên bên trái và góc dƣới bên phải của hình chữ nhật tƣơng ứng.
Dƣới đây, chúng ta sẽ mô tả chi tiết thủ tục Split().
Thuật toán CCS: Vào: I – ảnh , C - tập màu
minsize –ngƣỡng diện tích của một vùng, tolerance - ngƣỡng nhiễu
Ra: Các cụm màu thuần nhất trong ảnh.
For mỗi c C do { 1. Stack I
2. do
2.1 REC Stack
2.2 If (size(REC) > minsize)
2.2.1 if (deviation(REC)>tolerance) 2.2.1.1 Split(REC, c1, Rec1, c2, Rec2)
2.2.1.2 If (size(Rec1)>0) Stack Rec1 2.2.1.3 If (size(Rec2)>0) Stack Rec2
2.2.2 else xuất (c, REC) 3. while (Stack # ) }
Thủ tục Split() phân hoạch cụm REC thành hai cụm Rec1 và Rec2.
Thủ tục Split(REC, c1, Rec1, c2, Rec2)
Vào: Cụm REC với cỡ n n,
Ra: Các cụm và các màu của nó (c1, Rec1), (c2, Rec2)
1. for i0 to n-1 do 1.1 for j0 to n-1 do { row+ pi,j; afterrow+ pi1,j} 1.2 vi |( n ) i n , i min( *(row-afterrow)| 1.3 k Arg(max(<v1, v2,..., vn>)); kvmax(<v1, v2,..., vn>) 2. for j0 to n-1 do 2.1 for i0 to n-1 do { col+ pi,j ; aftercol+pi,j1} 2.2 hj | n ) j n , j min( *(col-aftercol)| 2.3 lArg(max(<h1, h2, ..., hn>)); lvmax(<h1, h2, ..., hn>) 3. if (kv > lv) then
3.1 Tách REC theo chiều đứng tại dòng k
3.2 Rec1size((0,0);(k,n-1)); c1color(Rec1)
3.3 Rec2size((k,0);(m-1,n-1)); c2color(Rec2)
4. else if (kv<lv) then
4.1 Tách REC theo chiều ngang tại cột l
4.2 Rec1size((0,0);(n-1,l)); c1color(Rec1)
4.3 Rec2size((0,l);(n-1,n-1)); c2color(Rec2)
5. else if (v1=v2=...=vn=h1=h2=...=hn) 5.1 Rec10;c1Null
5.2 Rec20;c2Null
Trong thủ tục này, tham số k giữ chỉ số dòng sẽ đƣợc sử dụng để tách theo chiều đứng và l giữ lại chỉ số cột sẽ đƣợc sử dụng để tách theo chiều ngang. kv nhận giá trị lớn nhất của danh sách <v1, v2, ... vn> và lv nhận giá trị lớn nhất của danh sách <h1, h2, ... hn>.
Với mỗi dòng i (i=0,1,…,n-1), Split() tính tổng số các điểm ảnh của dòng i và tổng các điểm ảnh của dòng i+1. Sau đó, nó tính giá trị độ lệch theo chiều đứng vi
của hai tổng này. Tƣơng tự, với mỗi cột j (j=0,1,…,n-1), Split() cũng tính toán giá trị độ lệch theo chiều ngang hj giữa tổng số các điểm ảnh trong cột j và cột j +1.
Dựa trên các giá trị |vi| và |hj| tính đƣợc, thủ tục Split() sẽ phân hoạch vùng
REC thành hai vùng Rec1 và Rec2 theo chiều ngang hoặc chiều đứng. Thủ tục Split() sẽ xuất ra các vùng Rec1, Rec2 và các màu c1, c2 tƣơng ứng của nó.
Ví dụ 3.3: Hình 3.7 chỉ ra một ảnh gồm 610 điểm ảnh. 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 2 1 1 1 0 1 0 0 1 1 1 3 1 1 1 0 0 0 1 1 1 1 4 1 1 1 1 1 1 1 1 1 1 5 1 1 1 1 1 1 1 1 1 1 6 1 2 3 4 5 6 7 8 9 10 Hình 3.7. Ảnh gồm 610 điểm ảnh.
Bảng 3.5. Tính toán giá trị của vi.
Thứ tự j j , i p j j , 1 i p vi 1 8 8 0 2 8 7 0.3 3 7 7 0 4 7 10 1 5 10 10 0
Bảng 3.6. Tính toán giá trị của hj. 6 6 6 3 3 3 5 6 6 i j i p, 6 6 3 3 3 5 6 6 6 i j i p, 1 0 0 0.9 0 0 0.8 0.3 0 0 hj 1 2 3 4 5 6 7 8 9 Thứ tự
Trong ví dụ này, các vùng đƣợc tách ra thành hai vùng con theo chiều đứng tại dòng thứ tƣ (k=4) (xem trong Bảng 3.5 và Bảng 3.6).
Dƣới đây chúng tôi sẽ đánh giá độ phức tạp của thủ tục Split() thông qua Mệnh đề 3.2.
Mệnh đề 3.2 [Độ phức tạp của thủ tục Split]:
Độ phức tạp của thủ tục Split() là O(n) với n là số điểm ảnh của ảnh,
Chứng minh:
Rõ ràng rằng, độ phức tạp thời gian của thủ tục Split() là độ phức tạp thời gian lớn nhất của một trong các bƣớc từ 1 đến 6. Chúng ta cũng dễ dàng nhận thấy, bƣớc 1 có độ phức tạp thời gian là O(n), bƣớc 2 có độ phức tạp thời gian là O(n) và các bƣớc 3, 4, 5 và 6 đều có độ phức tạp thời gian là O(1).
Do đó, độ phức tạp thời gian của thủ tục Split() là O(n). Mệnh đề đã đƣợc chứng minh.
Dƣới đây chúng tôi sẽ đánh giá độ phức tạp của thuật toán CCS thông qua Mệnh đề 3.3.
Mệnh đề 3.3 [Độ phức tạp của thuật toán CCS]:
Độ phức tạp của thuật toán CCS là O(n2) với n là số điểm ảnh của ảnh,
Rõ ràng rằng, độ phức tạp của thuật toán CCS là thời gian thực hiện lệnh
do…while. Đối với lệnh này, chúng ta dễ dàng nhận thấy số lần lặp tối đa là
size min
n
(với minsize là số điểm ảnh của cửa sổ và là hằng số) và thời gian thực
hiện của thân vòng lặp chính là độ phức tạp của thủ tục Split(). Hơn nữa, thủ tục Split() có độ phức tạp thời gian là O(n) (xem Mệnh đề 3.3). Vì vậy, thời gian để
thực hiện lệnh do…while là ) size min n ( O 2 .
Do đó, độ phức tạp thời gian của thuật toán CCS là O(n2). Mệnh đề đã đƣợc chứng minh.