Đõy là bước để hạn chế được cỏc vựng đốm dựa theo cửa sổ lọc nhiễu được chọn là 5x5, 3x3 và vị trớ thay đổi của vựng ảnh. Một tập Iwb được xử lý để lấy được vị trớ của vựng sỏng. Nếu vị trớ của vựng sỏng thay đổi nhỏ hơn một giỏ trị ngưỡng thỡ được coi là nhiễu, và lập tức được dập tắt. Kết quả chỳng ta cú được ảnh đen trắng Iwb được lọc. Vựng sỏng cú độ lớn 1 điểm ảnh sẽ được dập tắt bởi cửa sổ 3x3.
Hỡnh 6.26 dưới đõy minh họa kết quả của ảnh Iwb chưa lọc nhiễu và đó được lọc nhiễu.
Hỡnh 6.26. a), b) là 2 khung hỡnh cú độ sai khỏc thỏa món ngưỡng, c) Ảnh Iwb chưa lọc nhiễu, d) là ảnh Iwb sau khi lọc nhiễu 6.7.2.3. Phỏt hiện biờn ảnh đa cấp xỏm Igc
Trong quỏ trỡnh này, ảnh xỏm hiện thời Igc được phỏt hiện biờn dựa theo kỹ thuật phỏt hiện biờn đó đề xuất được trỡnh bày trong chương 2. Từ trờn cú thể xỏc định được ảnh biờn của đối tượng chuyển động.
c) Ảnh Iwb chưa lọc nhiễu d) Ảnh Iwb đó lọc nhiễu a) Ảnh khung hỡnh liền trước Ip b) Ảnh khung hỡnh hiện thời
Hỡnh 6.27. a), b) là 2 ảnh biờn cú độ sai khỏc thỏa món ngưỡng, c) Ảnh biờn của đối tượng chuyển động sau khi lọc nhiễu 6.7.2.4. Kết hợp ảnh Igc với Iwb
Ảnh sau khi đó được phỏt hiện biờn Iec được xếp chồng với ảnh đen trắng Iwb. Vựng đen trắng kết hợp với điểm biờn sẽ cho ta được tập hợp cỏc điểm bao quanh vựng chuyển động. Những điểm biờn của Iec gần với vựng trắng của Iwb được đỏnh dấu lại trờn Igc.
Hàm WB_Edge() trả về giỏ trị đỳng nếu điểm p là biờn, ngược lại trả về giỏ trị sai. Hàm GetPointEdge() sẽ thực hiện lấy điểm biờn trờn Iec sai lệch với điểm Iwb(p) là 2 đơn vị. Kết quả điểm biờn trả về sẽ là điểm gần nhất. Nếu khụng cú kết quả, trả về điểm trắng (giỏ trị trả về là 255) thỡ điểm Iwb(p) được coi là biờn của ảnh Igc. Điểm này sẽ được lưu lại. Những điểm được lưu lại sẽ được xử lý để lấy được hỡnh bao quanh đối tượng chuyển động đú. Và quỏ trỡnh phỏt hiện được vựng biờn của đối tượng chuyển động kết thỳc.
Hệ thống phỏt hiện khung chuyển động của đối tượng liờn tục đọc hai ảnh rồi lấy khung và in ra.
Dưới đõy là một số hỡnh ảnh kết quả đạt theo hướng tiếp cận kết hợp. Đoạn băng video cú dạng avi, được quay tại ngó ba Bắc Nam của thành phố Thỏi Nguyờn. Đoạn băng cú độ lớn 14,01 MB. Kết quả cho thấy thuật toỏn phỏt hiện khỏ tốt cỏc đối tượng chuyển động với cỏc tốc độ chuyển động khỏc nhau: ễtụ, xe mỏy, xe đạp. Hỡnh 6.28 là một số hỡnh ảnh thu được và đó được phỏt hiện cỏc đối tượng chuyển động.
c) Ảnh biờn của đối tượng chuyển động
Phụ lục 1:
MỘT SỐ ĐỊNH DẠNG TRONG XỬ Lí ẢNH
Hiện nay trờn thế giới cú trờn 50 khuụn dạng ảnh thụng dụng. Sau đõy là một số định dạng ảnh hay dựng trong quỏ trỡnh xử lý ảnh hiện nay.
1. Định dạng ảnh IMG
Ảnh IMG là ảnh đen trắng, phần đầu của ảnh IMG cú 16 byte chứa cỏc thụng tin:
• 6 byte đầu: dựng để đỏnh dấu định dạng ảnh. Giỏ trị của 6 byte này viết dưới dạng Hexa: 0x0001 0x0008 0x0001
• 2 byte tiếp theo: chứa độ dài mẫu tin. Đú là độ dài của dóy cỏc byte kề liền nhau mà dúy này sẽ được lặp lại một số lần nào đú. Số lần lặp này sẽ được lưu trong byte đếm. Nhiều dóy giống nhau được lưu trong một byte.
• 4 byte tiếp: mụ tả kớch cỡ pixel.
• 2 byte tiếp: số pixel trờn một dũng ảnh. • 2 byte cuối: số dũng ảnh trong ảnh.
Ảnh IMG được nộn theo từng dũng, mỗi dũng bao gồm cỏc gúi (pack). Cỏc dũng giống nhau cũng được nộn thành một gúi. Cú 4 loại gúi sau:
• Loại 1: Gúi cỏc dũng giống nhau.
Quy cỏch gúi tin này như sau: 0x00 0x00 0xFF Count. Ba byte đầu tiờn cho biết số cỏc dóy giống nhau, byte cuối cho biết số cỏc dũng giống nhau.
• Loại 2: Gúi cỏc dóy giống nhau.
Quy cỏch gúi tin này như sau: 0x00 Count. Byte thứ hai cho biết số cỏc dóy giống nhau được nộn trong gúi. Độ dài của dóy ghi ở đầu tệp.
• Loại 3: Dóy cỏc Pixel khụng giống nhau, khụng lặp lại và khụng nộn được.
Quy cỏch gúi tin này như sau: 0x80 Count. Byte thứ hai cho biết độ dài dóy cỏc pixel khụng giống nhau khụng nộn được.
Tuỳ theo cỏc bớt cao của byte đầu tiờn được bật hay tắt. Nếu bớt cao được bật (giỏ trị 1) thỡ đõy là gúi nộn cỏc byte chỉ gồm bớt 0, số cỏc byte được nộn được tớnh bởi 7 bớt thấp cũn lại. Nếu bớt cao tắt (giỏ trị 0) thỡ đõy là gúi nộn cỏc byte gồm toỏn bớt 1. Số cỏc byte được nộn được tớnh bởi 7 bớt cũn lại.
Cỏc gúi tin của file IMG rất đa dạng do ảnh IMG là ảnh đen trắng, do vậy chỉ cần 1 bớt cho 1 pixel thay vỡ 4 hoặc 8 như đó núi ở trờn. Toàn bộ ảnh chỉ cú những điểm sỏng và tối tương ứng với giỏ trị 1 hoặc 0. Tỷ lệ nộn của kiểu định dạng này là khỏ cao.
2. Định dạng ảnh PCX
Định dạng ảnh PCX là một trong những định dạng ảnh cổ điển. Nú sử dụng phương phỏp mó hoỏ loạt dài RLE (Run – Length – Encoded) để nộn dữ liệu ảnh. Quỏ trỡnh nộn và giải nộn được thực hiện trờn từng dạng ảnh. Thực tế, phương phỏp giải nộn PCX kộm hiệu quả hơn so với kiểu IMG. Tệp PCX gồm 3 phần: đầu tệp (header), dữ liệu ảnh (Image data) và bảng màu mở rộng.
Header của tệp PCX cú kớch thước cố định gồm 128 byte và được phõn bố như sau:
• 1 byte: chỉ ra kiểu định dạng.Nếu là PCX/PCC thỡ nú luụn cú giỏ trị là 0Ah.
• 1 byte: chỉ ra version sử dụng để nộn ảnh, cú thể cú cỏc giỏ trị sau: + 0: version 2.5.
+ 2: version 2.8 với bảng màu.
+ 3: version 2.8 hay 3.0 khụng cú bảng màu. + 5: version 3.0 cố bảng màu.
• 1 byte: chỉ ra phương phỏp mó hoỏ. Nếu là 0 thỡ mó hoỏ theo phương phỏp BYTE PACKED, ngược lại là phương phỏp RLE. • 1 byte: Số bớt cho một điểm ảnh plane.
• 1 word: toạ độ gúc trỏi của ảnh. Với kiểu PCX nú cú giỏ trị là (0,0), cũn PCC thỡ khỏc (0,0).
• 1 word: toạ độ gúc phải dưới.
• 1 word: kớch thước bề rộng và bề cao của ảnh. • 1 word: số điểm ảnh.
• 1 word: độ phõn giải màn hỡnh. • 1 word.
• 48 byte: chia nú thành 16 nhúm, mỗi nhúm 3 byte. Mỗi nhúm này chứa thụng tin về một thanh ghi màu. Như vậy ta cú 16 thanh ghi màu.
• 1 byte: khụng dựng đến và luụn đặt là 0.
• 1 byte: số bớt plane mà ảnh sử dụng. Với ảnh 16 màu, giỏ trị này là 4, với ảnh 256 mầu (1pixel/8bits) thỡ số bớt plane lại là 1.
• 1 byte: số bytes cho một dũng quột ảnh. • 1 word: kiểu bảng màu.
• 58 byte: khụng dựng.
Định dạng ảnh PCX thường được dựng để lưu trữ ảnh và thao tỏc đơn giản, cho phộp nộn và giải nộn nhanh. Tuy nhiờn, vỡ cấu trỳc của nú cố định, nờn trong một số trường hợp làm tăng kớch thước lưu trữ. Cũng vỡ nhược điểm này mà một số ứng dụng sử dụng một kiểu định dạng khỏc mềm dẻo hơn: định dạng TIFF (Targed Image File Format) sẽ mụ tả dưới đõy.
3. Định dạng ảnh TIFF
Kiểu định dạng TIFF được thiết kế để làm nhẹ bớt cỏc vấn đề liờn quan đến việc mở rộng tệp ảnh cố định. Về cấu trỳc, nú cũng gồm 3 phần chớnh:
• Phần Header(IFH): cỳ trong tất cả cỏc tệp TIFF và gồm 8 byte:
+ 1 word: chỉ ra kiểu tạo tệp trờn mỏy tớnh PC hay mỏy Macintosh. Hai loại này khỏc nhau rất lớn ở thứ tự cỏc byte lưu trữ trong cỏc số dài 2 hay 4 byte. Nếu trường này cú giỏ trị là 4D4Dh thỡ đú là ảnh cho mỏy Macintosh, nếu là 4949h là của mỏy PC.
+ 1 word: version. từ này luụn cú giỏ trị là 42. đõy là đặc trưng của file TIFF và khụng thay đổi.
+ 2 word: giỏ trị Offset theo byte tớnh từ đầu tới cấu trỳc IFD là cấu trỳc thứ hai của file. Thứ tự cỏc byte này phụ thuộc vào dấu hiệu trường đầu tiờn.
• Phần thứ 2(IFD): Khụng ở ngay sau cấu trỳc IFH mà vị trớ được xỏc định bởi trường Offset trong đầu tệp. Cú thể cú một hay nhiều IFD cựng tồn tại trong một file.
Một IFD bao gồm:
+ 4 byte: chứa Offset trỏ tới IFD tiếp theo. Nếu đõy là IFD cuối cựng thỡ trường này cú giỏ trị 0.
• Phần thứ 3: cỏc DE: cỏc DE cú dộ dài cố định gồm 12 byte và chia làm 4 phần:
+ 2 byte: chỉ ra dấu hiệu mà tệp ảnh đú được xõy dựng.
+ 2 byte: kiểu dữ liệu của tham số ảnh. Cú 5 kiểu tham số cơ bản: 1: BYTE (1 byte) 2: ASCII (1 byte) 3: SHORT (2 byte). 4: LONG (4 byte) 5: RATIONAL (8 byte)
+ 4 byte: trường độ dài chưa số lượng chỉ mục của kiểu dữ liệu đú chỉ ra. Nú khụng phải là tổng số byte cần thiết để lưu trữ. Để cú số liệu này ta cần nhõn số chỉ mục với kiểu dữ liệu đó dựng.
+ 4 byte: đú là Offset tới điểm bắt đầu dữ liệu liờn quan tới dấu hiệu, tức là liờn quan với DE khụng phải lưu trữ vật lý cựng với nú nằm ở một vị trớ nào đú trong file.
Dữ liệu chứa trong tệp thường được tổ chức thành cỏc nhúm dũng (cột) quột của dữ liệu ảnh. Cỏch tổ chức này làm giảm bộ nhớ cần thiết cho việc đọc tệp. Việc giải nộn được thực hiện theo 4 kiểu khỏc nhau được lưu trữ trong byte dấu hiệu nộn.
4. Định dạng file ảnh BITMAP
Mỗi file BITMAP gồm đầu file chứa cỏc thụng tin chung về file, đầu thụng tin chứa cỏc thụng tin về ảnh, một bảng màu và một mảng dữ liệu ảnh. Khuụn dạng được cho như sau:
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
RGBQUAD aColors[];
BYTE aBitmapBits[];
Trong đú, cỏc cấu trỳc được định nghĩa như sau:
typedef struct tagBITMAPFILEHEADER { /* bmfh */
UINT bfType;
DWORD bfSize;
UINT bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER { /* bmih */ DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER, *LPBITMAPINFOHEADER; với
biSize kớch thước của BITMAPINFOHEADER
biWidth Chiều rộng của ảnh, tớnh bằng số điểm ảnh biHeight Chiều cao của ảnh, tớnh bằng số điểm ảnh biPlanes Số plane của thiết bị, phải bằng 1
biBitCount Số bit cho một điểm ảnh biCompression Kiểu nộn
biSizeImage Kớch thước của ảnh tớnh bằng byte
biXPelsPerMeter độ phõn giải ngang của thiết bị, tớnh bằng điểm ảnh trờn met biYPelsPerMeter độ phõn giải dọc của thiết bị, tớnh bằng điểm ảnh trờn met biClrUsed Số lượng cỏc màu thực sự được sử dụng
biClrImportant Số lượng cỏc màu cần thiết cho việc hiển thị, bằng 0 nếu tất cả cỏc màu đều cần để hiển thị Nếu bmih.biBitCount > 8 thỡ mảng màu rgbq[] trống, ngược lại thỡ mảng màu cú 2<< bmih.biBitCount phần tử.
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD; Ta cũng cú:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
Phụ lục 2:
CÁC BƯỚC THAO TÁC VỚI FILE AVI
AVI là chuẩn video thường được tớch hợp trong cỏc thư viện của cỏc mụi trường lập trỡnh. Để xử lý video, cần cú cỏc thao tỏc cơ bản để chuyển về xử lý ảnh cỏc khung hỡnh (cỏc frames).
1. Bước 1: Mở và đúng thư viện
Trước mọi thao tỏc với file AVI, chỳng ta phải mở thư viện:
AVIFileInit( )
Hàm này khụng cần tham số, cú nhiệm vụ khởi động thư viện cung cấp cỏc hàm thao tỏc với file AVI. (Đú là thư viện vfw32.lib, được khai bỏo trong file vfw.h).
Sau tất cả cỏc thao tỏc bạn phải nhớ đúng thư viện đó mở lỳc đầu, chỉ bằng lệnh:
AVIFileExit( )
Nếu thiếu bất cứ hàm nào, dự là mở hay đúng thư viện thỡ trỡnh biờn dịch đều sẽ thụng bỏo lỗi.
2. Bước 2: Mở và đúng file AVI để thao tỏc:
Sau khi mở thư viện, bạn phải mở file AVI bạn định thao tỏc:
AVIFileOpen(PAVIFILE* ppfile, LPCSTR fname, UINT mode, CLSID pclsidHandler)
Thực chất, hàm này tạo ra một vựng đệm chứa con trỏ trỏ đến file cú tờn là fname cần mở. Và ppfile là con trỏ trỏ đến vựng bộ đệm đú. Tham số mode quy định kiểu mở file; chẳng hạn OF_CREATE để tạo mới, OF_READ để đọc, OF_WRITE để ghi …. Tham số cuối dựng là NULL.
Trước khi đúng thư viện, bạn phải đúng file AVI đó mở, bằng cỏch dựng hàm:
AVIFileRelease(PAVIFILE pfile)
3. Bước 3:
Mở dũng dữ liệu hỡnh ảnh hay õm thanh trong file AVI đó mở ra để thao tỏc:
AVIFileGetStream(PAVIFILE pfile, PAVISTREAM * ppavi, DWORD fccType, LONG lParam)
Trong đú, pfile là con trỏ đến file đó mở; ppavi trỏ đến dũng dữ liệu kết quả; fccType là loại dũng dữ liệu chọn để mở, là streamtypeAUDIO nếu là tiếng và streamtypeVIDEO nếu là hỡnh,… lParam đếm số loại dũng được mở, là 0 nếu chỉ thao tỏc với một loại dũng dữ liệu.
Sau cỏc thao tỏc với dũng dữ liệu này, bạn nhớ phải đúng nú lại:
AVIStreamRelease(PAVITREAM pavi).
4. Bước 4: Trường hợp thao tỏc với dữ liệu hỡnh của phim
Chuẩn bị cho thao tỏc với khung hỡnh (frames):
AVIStreamGetFrameOpen(PAVISTREAM pavi,
LPBITMAPINFOHEADER lpbiWanted)
Trong đú pavi trỏ đến dũng dữ liệu đó mở, lpbiWanted là con trỏ trỏ đến cấu trỳc mong muốn của hỡnh ảnh, ta dựng NULL để sử dụng cấu trỳc mặc định.
Hàm này trả về đối tượng cú kiểu PGETFRAME để dựng cho bước 5. Sau khi thao tỏc với cỏc frame rồi, phải gọi hàm :
AVIStreamGetFrameClose(PGETFRAME pget)
5. Bước 5: Thao tỏc với frame
Dựng hàm
AVIStreamGetFrame(PGETFRAME pget, LONG lpos)
Hàm này trả về con trỏ trỏ đến dữ liệu của frame thứ lpos. Dữ liệu đú cú kiểu là DIB đó định khối.
Phụ lục 3:
MỘT SỐ MODUL CHƯƠNG TRèNH
1. Nhúm đọc, ghi và hiển thị ảnh1.1. Nhúm đọc ảnh 1.1. Nhúm đọc ảnh
HDIB WINAPI ReadPCXFile(HFILE hf) {
PCXHEADER pcx;
if (!::ReadPCXHeader(hf, &pcx)) return NULL; // make a new bitmap header
BITMAPINFOHEADER bmi;
::InitBitmapInfoHeader(&bmi, (DWORD)(pcx.window.xmax- pcx.window.xmin+1), (DWORD)(pcx.window.ymax-
pcx.window.ymin+1), pcx.bitsperpixel); // Locate the memory
HDIB hDIB = ::GlobalAlloc(GMEM_MOVEABLE, (DWORD)sizeof(BITMAPINFOHEADER) +
(DWORD)::PaletteSize((LPSTR)&bmi) + bmi.biSizeImage); if (!hDIB) return NULL; // Fail
LPBITMAPINFOHEADER pDIB =
(LPBITMAPINFOHEADER)::GlobalLock(hDIB); *pDIB = bmi;
DWORD wBytes = (WORD)WIDTHBYTES(pDIB→biWidth*pDIB→ biBitCount); /*--- DU LIEU CHUNG ---*/ W = wBytes; nH = (int)pDIB→biHeight; nW = pDIB→biWidth; lpRGB = (LPRGBQUAD)(pDIB + 1); pImage = ((HBYTE)::FindDIBBits((LPSTR)pDIB));
/*---*/
HBYTE pLine = ((HBYTE)::FindDIBBits((LPSTR)pDIB)) + wBytes*(pDIB→biHeight-1);
WORD sizeBuff = 10240, // 10 KB index = 10, cr = 0, tmp = 0;
HGLOBAL hBuffers = ::GlobalAlloc(GMEM_MOVEABLE, sizeBuff+64);
HBYTE pBuffers = (HBYTE)::GlobalLock(hBuffers); for(int i=0;i<256;++i) { HistogramC[i] = 0; MauNen[i] = 0; } int L; BYTE Color; DWORD d=0;
for (i = 0; i < (int)pDIB→biHeight; i++) {
DWORD total = 0;
while (total < pcx.bytesperline) {
if (index >= cr) // Buffers {
if ((tmp > 0)&&(index == cr)) pBuffers[0] = pBuffers[index]; else tmp = 0;
index = 0; #ifdef _WIN32
cr = _lread(hf, (LPVOID)(pBuffers+tmp), sizeBuff); d+=cr;
#else
if (!tmp) {tmp = 1; cr--;} }
static BYTE b;
if ((b = pBuffers[index++]) >= 0xC0) // Get first byte { b &= 0x3F; if (total < wBytes) #ifdef _WIN32 { L = min((int)b, (int)(wBytes-total)); memset((void*)(pLine+total),(Color=pBuffers[index++]),L); HistogramC[Color] += L; } #else #endif// _WIN32 total += (WORD)b; }
else if (total < wBytes) { pLine[total++] = b; ++HistogramC[b]; } else total++; } pLine -= (LONG)wBytes; } LPRGBQUAD lpRGB = (LPRGBQUAD)(pDIB + 1); if (pDIB→biBitCount == 1) // Create the Look Up Table {
lpRGB[0].rgbRed = lpRGB[0].rgbGreen = lpRGB[0].rgbBlue = 0; // Black
lpRGB[0].rgbReserved = lpRGB[1].rgbReserved = 0; } else // 8 bit image, read LUT from file