Đối với mới điểm ảnh đều được biểu diễn bằng ba màu cơ bản RGB. Từ đầu vào là không gian màu RGB ta có để tìm không gian màu của HSV như sau:
B1: tìm giá trị max, min của (R,G,B) tương ứng với từng điểm ảnh một.
Đầu vào
(RGB) Đầu ra
(HSV)Bộ chuyển đổi Bộ chuyển đổi
Nếu max(R,G,B)=min(R,G,B) thì S=H=0.
Ngược lại thì thực hiện B2 ,B3 sau đây.
B2: gán giá trị của V là: V=max(R,G,B) (3.6) B3:gắn giá trị của S là: S= (max(R,G,Bmax()−min(R,GR,B,G) ,B))*255)
(3.7) B4: tìm H trong các trường hợp sau:
Nếu :max(R,G,B)=R. Và nếu G>=B thì S B G H =( − )*60 (3.8) Ngược lại G<B thì S B G H =360+( − )*60 (3.9) Nếu :max(R,G,B)=G thì S B G H =120+( − )*60 (3.10) Nếu :max(R,G,B)=B thì S B G H =240+( − )*60 (3.11) Code của chương trình này là.
minRGB=min3(R,G,B); maxRGB=max3(R,G,B); if(maxRGB==minRGB) { S=H=0; V=maxRGB=minRGB; } else { V=maxRGB; S=(maxRGB-minRGB)*255/maxRGB; if (maxRGB==R if (G>=B) { H= ((G-B)*60/S); } else { H=360+((G-B)*60/S); } } else if((maxRGB==G)) { H=120+(G-B)*60/S;
}
else
{
H=(240+((R-G)*60)/S); }
Kết quả của chương trình bộ chuyển đổi RGB sang HSV với nguồn ảnh đầu vào là ảnh ở hình 3.8(b) ( ảnh đã ra khỏi bộ lọc trung bình ) được thể hiện ở hình vẽ dưới đây.
Hình 3.10: Ảnh khi được chuyển đổi sang HSV.
Từ hình 3.10 ta thấy ảnh đã được chuyển từ không gian màu RGB sang HSV.
3.2.3 Phân ngưỡng.
Hình 3.11: Sơ đồ bộ phân ngưỡng.
Như đã giới thiệu ở phần trên ảnh cà phê thu được thường có chứa hạt cà phê xấu, tốt và background gọi chung là object và background. Nếu ảnh cà phê thu được chỉ đơn thuần không chịu tác động bởi cường độ chiếu sáng. Thì khi đó chúng ta hoàn hoàn toàn đơn giản trong việc tách ngưỡng. Lúc đó để tách ngưỡng ta chỉ quan tâm đến màu của hạt xấu. Vì mẫu vật xấu đều đã biết được cho nên ta đã biết được màu của hạt xấu nằm trong dải màu nào từ đó ta gắn cố định dải màu đó. Dựa vào đó chúng ta có thể tách được hạt xấu trong ảnh mà ta thu được. Do vậy, ta phải xây dựng một thư viện để xác
định các loại hạt xấu. Dựa vào thư viện này ta có thể xác định được hạt xấu xuất hiện trong ảnh.
Song trong thực tế, ảnh mà chúng ta thu nhận được không chỉ đơn giản như vậy, ảnh thu nhận về còn bị ảnh hưởng bởi độ chiếu sáng. Do đó, nhiệm vụ quan trọng nhất là đối phó được với sự chiếu sáng. Như đã trình bày ở phần trên, chúng ta dùng không gian màu HSV để dễ dàng cho việc nhận dạng màu sắc. Ta đã biết đặc tính của không gian màu có đặc tính như sau: H là bước sóng của ánh sáng, V là cường độ ánh sáng, S là độ tinh khiết của ánh sáng gốc. Cho nên, để chọn ngưỡng cho ảnh thì ta dựa trên dải giá trị của H. Đó là dải mà ta coi nó là hạt xấu trong thư viện các hạt xấu mà ta đã đưa ra. Dải giá trị trong ngưỡng này là dựa trên các mẫu đã biết trước và được ta đưa vào không gian màu của HSV ở trên. Trong khi đó từ không gian màu HSV ta thấy nếu giá trị của V mà lớn thì tương ứng giá trị của S cũng lớn và ngược lại nếu giá trị của V mà nhỏ thì giá trị của S cũng nhỏ theo (vì bán kính của vòng tròn trong không gian màu phụ thuộc vào giá trị trục đứng của V trong không gian màu HSV). Do vậy, nếu giá trị của V bị thay đổi thì đống nghĩa với giá trị cường độ sáng cũng bị thay đổi và ngược lại. Cho nên, để chọn ngưỡng xử lý thì trước tiên ta phải chọn khoảng giá trị của H sau đó mới chọn khoảng giá trị của S bằng cách coi S là một hàm của V. Mặt khác V cũng là đại diện cho mức cường độ chiếu sáng của ảnh. Dưới đây là miêu tả thuật toán phân ngưỡng cho ảnh:
Các bước để xác định ngưỡng của hạt cà phê như sau:
Xác định khoảng giá trị của H mà chúng ta coi dải màu đó là dải màu của hạt xấu.
Tìm giá trị lớn nhất và nhỏ nhất của V.
Chọn S là một hàm mà V lại là một biến của hàm S. Cụ thể S được chọn như sau:
S > (maxV-minV)*H;
Với H là hệ số mà chúng ta phải tìm ra được cho phù hợp để nếu có bị chiếu sáng ảnh hưởng đến hạt cà phê thì nó cũng không gây ảnh hưởng nhiều đến kết quả của việc phân loại hạt cà phê.
Nếu dải hạt màu cà phê mà nằm trong dải màu như đã nếu trên thì ta coi đó là dải hạt xấu và quyết định nó có màu trắng, còn ngược lại nó sẽ có màu đen. Do vây, sau quá trình phân ngưỡng thì ảnh sau xử lý ảnh hạt cà phê thực chất chỉ là ảnh nhị phân.
Cho giá trị của V nằm trong khoảng: minV <V< maxV.
Sau bước này chúng ta phân ngưỡng được khoảng giá trị của hạt cà phê. Song ảnh sau khi thu được từ bước xử lý trên thì nhiễu có thể vẫn còn tồn tại trong ảnh. Để loại bỏ triệt để nhiễu chúng ta phải thực hiện bước lọc tiếp theo:
code của chương trình này là.
for(i=0; i < height; i++)
for(j=0; j < width; j++) {
if(psrc[i*bytewidth+3*j]>maxv)
maxv=psrc[i*bytewidth+3*j]; }
for(i=0; i < height; i++)
for(j=0; j < width; j++) { if(psrc[i*bytewidth+3*j]<minv) minv=psrc[i*bytewidth+3*j]; } s=(maxv-minv)*205/255; h>minv; h<maxv;
Kết quả của phép toán phân ngưỡng với ảnh đầu vào là ảnh ở hình 3.10 (ảnh đã được chuyển đổi thành HSV) được thể hiện ở hình vẽ sau:
Từ hình 3.12 trên ta thấy ảnh thu nhận được sau khi phân ngưỡng bao gồm cả hạt xấu và nhiễu. Nhiễu là các đối tượng nhỏ còn các hạt xấu mà ta quan tâm là các đối tượng lớn.
3.2.4 Lọc nhiễu.
Hình 3.13: Sơ đồ bộ lọc nhiễu.
Thuật toán lọc nhiễu được dùng trong quá trình xử lý này còn được gọi là Mophologyclose. Thuật toán này dựa trên hai phép “dãn” và “co”. Các bước xác định thuật toán lọc nhiễu Mophologyclose sẽ được chỉ ra dưới đây:
Để hiểu được thuật toán này trước tiên ta phải hiểu được phương pháp lập bảng tìm kiếm:
Mỗi pixel và 8 pixel lân cận của nó trong ảnh nhị phân có thể được biểu diễn một cách đầy đủ bởi một số nguyên dương 9 bit được thể hiện như hình sau:
Hình 3.14: Phương pháp lập bảng tìm kiếm.
B1: Thực hiện phép co ảnh :
Dựa vào phương pháp lập bảng tìm kiếm ta có được cách thực hiện sau. Từ pixel cũ X và lân cận của nó ta có thể suy ra được một pixel mới Y như sau:
76 6 5 4 3 2 1 0 X X X X X X X X X Y = ∩ ∩ ∩ ∩ ∩ ∩ ∩ ∩ (3.12) B2: Thực hiện phép dãn ảnh:
Cũng tương tự như phép co ảnh phép dãn ảnh cũng dựa vào bảng tìm kiếm ta có thể suy ra được pixel mới Y từ pixel cũ X và lân cận của nó như sau:
76 6 5 4 3 2 1 0 X X X X X X X X X Y = ∪ ∪ ∪ ∪ ∪ ∪ ∪ ∪ (3.13)
Trong thuật toán Mophologyclose thì ảnh được tạo ra từ phép co ảnh rồi sau đó mới đến phép dãn ảnh. Số lượng các bước co ảnh phải bằng với số lượng các bước dãn
Khóa luận tốt nghiệp Hà Thiên Sơn K49ĐB
Đầu vào Lọc nhiễu Đầu ra
ảnh. Qua thuật toán Mophologyclose đối tượng nhỏ bị mất hoàn toàn. các cấu trúc gờ cạch của đối tượng lõm cũng được san bằng. Các đối tượng ảnh sẽ thay đổi theo một cách không thuận nghịch. Song ảnh sau khi qua thuật toán Mophologyclose thì ảnh thường bị bé đi hay bị lõm. Do vậy ta nên thực hiện một thuật toán làm sao lấp đầy các đối tượng bị lõm. Đó chính là thuật toán Mophologyopen. Thuật toán này chính là ngược so với thuận toán Mophologyclose.
Thuât toán Mophologyopen được thực hiện bằng phép dãn ảnh, sau đó mới đến phép co ảnh, số lượng các phép dãn ảnh phải bằng số lượng các phép co ảnh. Thuật toán này có tác dụng các đối tượng nằm sát nhau cùng lớn lên, còn lỗ trống trong các đối tượng được khép kín lại và cấu trúc lõm ở mép đối tượng được làm đầy.
Code cho thuật toán Mophologyclose này là
// co
for(iter=0; iter<num_iterations; iter++) {
for(i=1; i<height-1; i++)
for(j=1; j<width-1; j++) { temp = i*width+j; if((input[temp]==255)&&getNeighbor(input,temp,wid th,true)) output[temp]=0; } memcpy(input,output,size); } // gian
for(iter=0; iter<num_iterations; iter++) {
for(i=1; i<height-1; i++)
for(j=1; j<width-1; j++) { temp = i*width+j;// if((input[temp]==0)&&getNeighbor(input,temp,width, false)) output[temp]=255; } memcpy(input,output,size); }
Code cho thuật toán Mophologyopen này là :
// gian
for(i=1; i<height-1; i++) for(j=1; j<width-1; j++) { temp = i*width+j; if((input[temp]=0)&&getNeighbor(input,temp,width, false)) output[temp]=255; } memcpy(input,output,size); } // co
for(iter=0; iter<num_iterations; iter++) {
for(i=1; i<height-1; i++)
for(j=1; j<width-1; j++) { temp = i*width+j; if((input[temp]=255)&&getNeighbor(input,temp,width, true)) output[temp]=0; } memcpy(input,output,size); }
Bool CBitmapReaderDoc::getNeighbor(unsigned char *input,
unsigned int index, int width, BOOL type) {
// co
if (type) {
if (input[index+1]==0)return true;
if (input[index-1]==0)return true;
if (input[index-width]==0)return true;
if (input[index-width+1]==0)return true;
if(input[index-width-1]==0)return true;
if(input[index+width]==0)return true;
if(input[index+width+1]==0)return true;
if(input[index+width-1]==0)return true; }
// gian
else
{
if (input[index+1]==255) return true;
if (input[index-1]==255) return true;
if (input[index-width]==255) return true;
if(input[index-width+1]==255)return true;
if(input[index-width-1]==255)return true;
if (input[index+width]==255)return true;
if(input[index+width+1]==255)return true;
if(input[index+width-1]==255)return true;
}
return false;
Kết quả của chương trình lọc nhiễu này với ảnh đầu vào là ảnh ở hình 3.12 (ảnh đã được phân ngưỡng) được thể hiện ở hình dưới đây:
a) b)
Hình 3.15: a: Ảnh sau khi được lọc nhiễu bởi thuật toán morpholoryclose b: Ảnh sau khi đã được qua lọc bởi thuật toán morpholoryopen.
Từ hình 3.15(a) ta thấy ảnh đã được lọc đi các đối tượng nhỏ, bằng cách ta so sánh ảnh ở hình 3.12 là ảnh chưa được lọc đi các đối tượng nhỏ và hình 3.15(a) là ảnh đã lọc đi được các đối tượng nhiễu đó. Do khi dùng thuật toán mopholoryclose thì các đối tượng nhỏ sẽ bị biến mất hoàn toàn còn các đối tượng lớn (các hạt xấu) bị nhỏ đi. Do vậy, ta phải thực hiện một thuật toán làm lớn các đối tượng xấu và lấp đầy lỗ trỗng cửa hạt xấu do quá trình phân ngưỡng gây ra. Bằng cách thực hiện thuật toán mophologyopen. Chúng được thể hiện bởi hình 3.15(b) trên.
3.2.5 Quyết định vị trí hạt xấu.
Hình 3.16: Sơ đồ bộ quyết định hạt xấu.
Đầu vào Quyết định vị trí Đầu ra hạt xấu
Sau khi lấy ngưỡng ảnh lúc này chỉ còn hai mức đen và trắng, mức trắng là mức mà ta coi đó là mức của hạt xấu, còn mức đen là mức mà là mức của hạt không không phải là xấu. Để tìm được trọng tâm của hạt xấu thì ta dựa vào thuật toán đệ quy là chủ yếu. Thuật toán này được trình bày như sau:
Thuật toán này chủ yếu dựa vào phép đệ quy để tìm được vị trí thuộc đối tượng xấu. Đầu tiên trong quá trình quét ảnh nếu tìm được pixel(i,j)=255; thì ta đánh dấu vị trí đó, sau đó dựa vào vị trí vừa đánh dấu đó tìm các lân cận gận nó xem có pixel nào cũng thuộc vật xấu nữa hay không. Nếu thuộc ta lại đánh dấu nó vào sau đó lại tìm pixel lân cận của nó. Cứ như vậy cho đến khi tìm được hết đối tượng xấu thì thôi. Khi đó dựa vào những tập hợp mà ta đã đánh dấu ta được một tập hợp các điểm thuộc vật xấu. Từ đó ta tính trung bình các các tập hợp đó ta sẽ tìm được trọng tâm của hạt cà phê xấu. Nội dung cụ thể của thuật toán này được trình bày cụ thể như sau:
B 1: Trong chiều quét ảnh nếu gặp pixel(i,j)=255; đánh dấu vị trí pixel này lại và pixel(i,j)=0 nhấy vào B1.1.
B 1.1: thiết lập hàm đệ quy mà nội dung của hàm này là: Đánh dấu vị trí hiện tại tức vị trí có pixel(i,j)=255; sau đó lưu giá trị tọa độ (i,j) . Tăng biến đếm mỗi khi được đánh dấu (area=area+1).
B 1.2: Kiểm tra các lân cận của pixel vừa được đánh dấu. Nếu có pixel nào có giá trị =255 thì quay lại B 1.1 tức là gọi lại hàm đệ quy trên. Cứ như vậy sẽ kiểm tra hết tất cả các lân cận của những pixel vừa được đánh dấu cho đến khi nào không còn pixel lân cận của những pixel đã được đánh dấu =255 thì thôi.
B 1.3: kiểm tra biến đếm area:
Nếu area >=sizeobj: thì coi đó là một đối tượng và nhẩy đến B 1.4
Nếu area <sizeobj: coi đó không phải là đối tượng nhẩy đến B1.5
Với sizeobj: là số đã cho trước.
B 1.4: Khi đến bước này thì chúng ta coi như là đã gặp được một đối tượng. Khi đó thể hiện bằng cách cho biến count đại diện cho biến đếm mỗi khi gặp được một đối tượng tức là count=count+1. Mặt khác khi đã tìm được một đối tượng xấu thi còn phải tìm trọng tâm của một đối tượng xấu đó. Trọng tâm=(Tổng tất cả các giá trị tọa độ mà đã
đánh dấu được)/ (tổng tất cả các pixel có trong đối tượng đó). Sau bước này nhẩy đến B2.
B 1.5: area=0; vì khi đó coi như đối tượng đang xét không phải là đối tượng vì nó quá nhỏ sau bước này nhẩy đến B 2:
B2: Tiếp tục quét ảnh bằng cách tăng biến i,j để xem có gặp đối tượng xấu nữa hay không. Nếu trong toàn bộ quá trình quét ảnh mà không gặp đối tượng xấu thì thôi. Còn nếu có gặp đối tượng xấu thì lại lập lại các B1 như trên.
Code của thuật toán này là:
Void couting(int sizeobj,int height,int width) { for(i=1;i<height-1;i++) for(j=1;j<width-1;j++) { if(input[i*bytewidth+3*j+2]==255) { area = 0; input[i*bytewidth+3*j+2]=0; dequy(input,&area,i,j,point); if(area>sizeobj) double x=0.0,y=0.0; for(m=0;m<area;m++) { x+=(double)point[m].x; y+=(double)point[m].y; } x /= (double)area; y /= (double)area; ar[count] = area; count++; else area =0; }
void dequy(int *count,int row,int col,POINT *point) { point[*count].x = row; point[*count].y = col; *count = *count +1; if(input[(row-1)*bytewidth+3*col+2]==255) { input[(row-1)*bytewidth+3*col+2]=0; dequy(input,count,(row-1), col, point); }
input[(row-1)*bytewidth+3*(col-1)+2]=0; dequy(input,count,(row-1),(col-1) ,point); } if(input[(row-1)*bytewidth+3*(col+1)+2]==255) { input[(row-1)*bytewidth+3*(col+1)+2]=0; dequy(input,count,(row-1), col+1, point); }
if(input[(row+1)*bytewidth+3*(col)+2]==255) {
input[(row+1)*bytewidth+3*(col)+2]=0; dequy(input,count,(row+1), (col), point); }
if(input[(row+1)*bytewidth+3*(col-1)+2]==255) {
input[(row+1)*bytewidth+3*(col-1)+2]=0; dequy(input,count,(row+1), col-1, point); }
if(input[(row+1)*bytewidth+3*(col+1)+2]==255) {
input[(row+1)*bytewidth+3*(col+1)+2]=0; dequy(input,count,(row+1), col+1, point); }
if(input[row*bytewidth+3*(col-1)+2]==255) {
input[row*bytewidth+3*(col-1)+2]=0; dequy(input,count,(row), col-1, point); } if(input[row*bytewidth+3*(col+1)+2]==255) { input[row*bytewidth+3*(col+1)+2]=0; dequy(input,count,(row), col+1,point); }
Hình dưới đây thể hiện việc xác định trọng tâm của hạt cà phê xấu với ảnh đầu vào là ảnh ở hình 3.15 (ảnh đã được lọc ) được thể hiện ở hình vẽ dưới đây.
Hình 3.17: Xác định tâm của hạt xấu.
Từ hình 3.17 trên ta thấy diện tích của vòng tròn là diện tích của mỗi hạt xấu. Tâm của các vòng tròn nhỏ bên trong mỗi hạt xấu chính là trọng tâm của hạt cà phê xấu. Vậy sau bước này ta đã thu được trọng tâm của một hạt xấu.
Mục đích của việc tìm trọng tâm của hạt xấu đó là dựa vào trọng tâm đó ta có thể gửi tín hiệu đến một bộ phận xử lý để bộ phận xử lý gửi đến bộ phận thổi hạt xấu vừa xác định được đó. Dưới đây là một ví dụ về cơ cấu thổi hạt xấu ra ngoài máng chứa hạt phế phẩm.