THUẬT TỐN VÀ CẤU TRÚC CHƯƠNG TRÌNH : -0-0-Chương trình Image Processing viết Net 3.5 , windows Vista ,C# visual studio 2008 sp1 -Tất giải thuật xử lý góp nhặt từ www.codeproject.com Chương trình sử dụng chủ yếu GDI+, RGB color space , ảnh thường chuyển đồi sang 24 b/pixel -Tài liệu tham khảo : Digital Image Processing By Gonzalez 2nd Edition 2002 (phần xử lý ảnh) số tài liệu rời rạc khác mạng I: Cấu trúc chương trình : - Chi tiết “CHUONG TRINH XU LY ANH !.chm” - MainForm : phần chương trình chứa tất Menu, Area,Layers đặc biệt file MrPro.cs (người lập trình đặt tên đùa vui khơng có ý khác), file quan trọng chứa class chứa function static làm nhiệm vụ xử lý ảnh, file nói kỹ phần sau -DifferentTwoImages.exe tiện ích viết bên ngồi chương trình sử dụng chương trình với chức so sánh tìm khác biệt ảnh -Ta có chương trình tương tự DifferentTwoImages.exe , ThuNghiem.exe chứa Control (hiện ảnh Zoom ảnh mà không bị giật áp dụng kĩ thuật vẽ đệm tạo vùng nhớ phụ cách làm DirectX) làm trọng tâm để xây dựng nên Area class MainForm II: Chi tiết giải thuật MrPro.cs -Chứa class khác , class làm nhiệm vụ xác định -Mỗi ảnh xử lý chuyển thành 24 b/pixel , color space RGB 1.CaoAn class - sử dụng giải thuật nhân ma trận để ảnh khác Ví dụ ta có ảnh với chiều dài W chiều cao H pixel ảnh (trừ viền bên ngồi khơng đáng kể) coi có pixels xung quanh Vậy ta có ma trận với S(x,y) hàm điểm ảnh đó, S(x,y) gọi mức xám x,y tương ứng với tọa độ điểm pixel ta tính đến Mỗi pixel xác định khơng gian chiều màu red, green blue Mỗi màu xác định từ 0->255 tương ứng byte Giải thuật nhân ma trận thực chất xác định ma trận điểm ảnh lấy ma trận nhân với ma trận chứng minh để xác định mức xám điểm trung tâm ma trận chúng tơi sử dụng ma trận 3x3 cho tiện sử dụng Việc nhân ma trận việc xác định ma trận nhân với ma trận định sẵn ,sau gán giá trị cho điểm ảnh , muốn tính tất điểm ảnh ta phải tạo vòng lặp chạy hết W H CaoAn class sử dụng ma trận 3x3 định nghĩa lớp Matrix MrPro.cs Người đọc tham khảo thêm “CHUONG TRINH XU LY ANH !.chm” -Các functions chủ yếu lớp viết dạng “ public static “ cho dễ sử dụng sau Gồm functions sau : a.Conv3x3 : nói function tìm ma trận 3x3 tồn ảnh nhân với ma trận truyền vào ảnh cần xử lý (ảnh chương trình thường truyền dạng tham chiếu biến đổi ảnh đoạn code ảnh tham chiếu đổi).Đây function trung tâm class này, functions lại làm nhiệm vụ lấy ảnh ma trân ứng với giải thuật tính sẵn sau gọi hàm Conv3x3 truyên biến vào mà b Embossing : Làm public static bool Embossing(Bitmap image, int Weight) { Matrix m = new Matrix(); m.TopLeft = -1; m.TopMid = 0; m.TopRight = -1; m.MidLeft = 0; m.Pixel = 4; m.MidRight = 0; m.BottomLeft = -1; m.BottomMid = 0; m.BottomRight = -1; m.Factor = Weight + 1; m.Offset = 127; return Conv3x3(image, m); } c GaussianBlur public static bool GaussianBlur(Bitmap image, int Weight) { Matrix m = new Matrix(); m.TopLeft = 1; m.TopMid = 2; m.TopRight = 1; m.MidLeft = 2; m.Pixel = 4; m.MidRight = 2; m.BottomLeft = 1; m.BottomMid = 2; m.BottomRight = 1; m.Factor = Weight + 16; return Conv3x3(image, m); } d MeanRemoval: hiệu ứng quan trọng giải thuật tìm góc cạnh ảnh , song chúng tơi chưa thể phát triển thêm public static bool MeanRemoval(Bitmap image, int Weight) { Matrix m = new Matrix(); m.TopLeft = -1; m.TopMid = -1; m.TopRight = -1; m.MidLeft = -1; m.Pixel = 9; m.MidRight = -1; m.BottomLeft = -1; m.BottomMid = -1; m.BottomRight = -1; m.Factor = Weight + 1; return Conv3x3(image, m); } e Sharpen : “Hiệu ứng yêu cầu đề tài” public static bool Sharpen(Bitmap image, int Weight) { Matrix m = new Matrix(); m.TopLeft = 0; m.TopMid = -2; m.TopRight = 0; m.MidLeft = -2; m.Pixel = 11; m.MidRight = -2; m.BottomLeft = 0; m.BottomMid = -2; m.BottomRight = 0; m.Factor = Weight + 3; return Conv3x3(image, m); } f Smooth public static bool Smooth(Bitmap image, int Weight)//Weight=1 by default { Matrix m = new Matrix(); m.SetAllVariables(1); m.Pixel = Weight; m.Factor = Weight + 8; return Conv3x3(image, m); } -Còn nhiều hiệu ứng khác song tiết kiến thức trình độ hiểu biết chưa sâu chúng tơi khơng lý giải tìm ma trận nhân đưa số lọc tham khảo mà //============================================================== b ColorValuated : class sử dụng giải thuật quét , quét toàn pixels ảnh từ gán sắc độ tạo nên ảnh - Cũng functions static a Amban : Lấy đảo lại màu public static bool Amban(Bitmap image)//Âm ban { BitmapData dabimage = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stretch = dabimage.Stride; int offset = stretch - image.Width * 3; IntPtr scan0 = dabimage.Scan0; unsafe { byte* p = (byte*)(void*)scan0; //byte red, green, blue; for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { p[0] = (byte)(255 - p[0]); p[1] = (byte)(255 - p[1]); p[2] = (byte)(255 - p[2]); p += 3; } p += offset; } } b Blue : tăng sắc xanh lục đến 255 làm cho ảnh có màu xanh nhận rõ ảnh public static bool Blue(Bitmap image, byte blue) { BitmapData dabimage = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stretch = dabimage.Stride; int offset = stretch - image.Width * 3; IntPtr scan0 = dabimage.Scan0; unsafe { byte* p = (byte*)(void*)scan0; //byte red, green, blue; for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { p[0] = (byte)blue; p += 3; } p += offset; } } image.UnlockBits(dabimage); return true; } c GrayScale : Thường dùng in ấn , chuyễn ảnh màu sang ảnh trắng đen public static bool GrayScale(Bitmap image) { BitmapData dabimage = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stretch = dabimage.Stride; int offset = stretch - image.Width * 3; IntPtr scan0 = dabimage.Scan0; unsafe { byte* p = (byte*)(void*)scan0; //byte red, green, blue; for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { p[0] = p[1]=p[2]=(byte)((p[0]+p[1]+p[2])/3); p += 3; } p += offset; } } image.UnlockBits(dabimage); return true; } d Green : tăng sắc xanh đến 255 làm cho ảnh có màu xanh nhận rõ ảnh public static bool Green(Bitmap image, byte green) { BitmapData dabimage = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stretch = dabimage.Stride; int offset = stretch - image.Width * 3; IntPtr scan0 = dabimage.Scan0; unsafe { byte* p = (byte*)(void*)scan0; //byte red, green, blue; for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { p[1] = (byte)green; p += 3; } p += offset; } } image.UnlockBits(dabimage); return true; } f Red : tăng sắc đỏ đến 255 làm cho ảnh có màu xanh nhận rõ ảnh public static bool Red(Bitmap image, byte red) { BitmapData dabimage = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stretch = dabimage.Stride; int offset = stretch - image.Width * 3; IntPtr scan0 = dabimage.Scan0; unsafe { byte* p = (byte*)(void*)scan0; //byte red, green, blue; for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { p[2] = (byte)red; p += 3; } p += offset; } } image.UnlockBits(dabimage); return true; } c.HoaiVu class : - Các lọc dựa chuyển đồi tọa độ pixels ảnh theo quy tắt Chúng tơi sử dụng DisplacementFilters function dịch tọa độ pixels Point[,] điểm thú vị nhầt class, sử dụng tọa độ mảng chiều tọa độ Do ta coi pixel ảnh cầm giữ tọa độ pixel khác cần coppy ảnh y hệt ảnh gốc gán pixel tọa độ tương ứng ta ảnh public static bool DisplacementFilters(Bitmap image, Point[,] offset) { Bitmap imageCopp = (Bitmap)image.Clone(); BitmapData bdimage = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData bdimagecopp = imageCopp.LockBits(new Rectangle(0, 0, imageCopp.Width, imageCopp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stride = bdimage.Stride; System.IntPtr scan0 = bdimage.Scan0; System.IntPtr scan0copp = bdimagecopp.Scan0; unsafe { byte* p = (byte*)(void*)scan0; byte* pcopp = (byte*)(void*)scan0copp; int nOffset = stride - image.Width * 3; int nx, ny;// bien vi tri int nWidth = image.Width; int nHeight = image.Height; for (int y = 0; y < nHeight; y++) { for (int x = 0; x < nWidth; x++) { nx = offset[x, y].X; ny = offset[x, y].Y; if (nx >= && nx < image.Width && ny >= && ny < image.Height) { p[0] = pcopp[nx * + ny * stride]; p[1] = pcopp[nx * + ny * stride + 1]; p[2] = pcopp[nx * + ny * stride + 2]; } p += 3; } p += nOffset; } } image.UnlockBits(bdimage); imageCopp.UnlockBits(bdimagecopp); return true; } -Các thuật tốn sau : + Xoay : thay dùng transform xoay tọa độ GDI+ vector System.Drawing.Drawing2D ta dùng thuật toán xoay ảnh hàm viết dùng nhiều trường hợp xoay ngang ảnh, xoay dọc ảnh public static bool Xoay(Bitmap image, bool ngang, bool dung) { Point[,] offset = new Point[image.Width, image.Height]; for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { offset[x, y].X = (ngang) ? image.Width - (x + 1) : x; offset[x, y].Y = (dung) ? image.Height - (y + 1) : y; } } DisplacementFilters(image, offset); return true; } + RandomFilter: lấy giá trị random , coi pixel vị trí lấy pixel vị trí dao động ta truyền vào public static bool RandomFilter(Bitmap image, int rad)//rad la so nguuyen image.Width) offset[x, y].X = image.Width; if (offset[x, y].Y < 0) offset[x, y].Y = 0; if (offset[x, y].Y > image.Height) offset[x, y].Y = image.Height; } } DisplacementFilters(image, offset); return true; } + CheoAnh : ảnh tách xen kẽ dòng pixels tùy thuộc vào giá trị biến truyền vào public static bool CheoAnh(Bitmap image, int bien)//mac dinh la keo anh ngang bien xac dinh gia tri keo { Point[,] offset = new Point[image.Width, image.Height]; for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++) { offset[x, y].X = x + bien; offset[x, y].Y = y + bien; if (offset[x, y].X < 0) offset[x, y].X = 0; if (offset[x, y].X > image.Width) offset[x, y].X = image.Width; if (offset[x, y].Y < 0) offset[x, y].Y = 0; if (offset[x, y].Y > image.Height) offset[x, y].Y = image.Height; bien = -bien; } } DisplacementFilters(image, offset); return true; } -Hướng phát triển tiếp không gian House.Hiện hiểu chưa ứng dụng vào xử lý ảnh, mong phát triển sau ImageResizing -Đây class viết riêng cho việc phóng to thu nhỏ ảnh Class phát triển function ScaleByPercent làm nhiệm vụ Resize ảnh theo tỉ lệ phần trăm Nhược điểm lớn sử dụng GDI+ , hàm xử lý tuyến tính ảnh thu nhỏ phóng to tất nhiên khơng phục hồi nguyên trạng pixels public static Image ScaleByPercent(Image imgPhoto, int Percent) { float nPercent = ((float)Percent / 100); int sourceWidth = imgPhoto.Width; int sourceHeight = imgPhoto.Height; int sourceX = 0; int sourceY = 0; int destX = 0; int destY = 0; int destWidth = (int)(sourceWidth * nPercent); int destHeight = (int)(sourceHeight * nPercent); Bitmap bm_Image = new Bitmap(destWidth, destHeight, PixelFormat.Format24bppRgb); bm_Image.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution); Graphics image_graphic = Graphics.FromImage(bm_Image); image_graphic.InterpolationMode = InterpolationMode.HighQualityBicubic; image_graphic.DrawImage(imgPhoto,new Rectangle(destX, destY, destWidth, destHeight), new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), GraphicsUnit.Pixel); image_graphic.Dispose(); return bm_Image; } DifferentImage class - form viết ngồi chương trình tham chiếu assembly ( Dương Quang Thiện ) dùng để so sánh ảnh - LinerCaculate function quan trọng form Giải thuật chủ yếu quét (như ColorValuated ) so sánh pixel tơ đen , khác cho màu (lưu ý màu khoảng cách màu pixel khác ,nếu khoảng cách =0 hiển nhiên màu tức đen ) private void LinerCalculate(Bitmap inImage, Bitmap sImage) { if (inImage.Height != sImage.Height || inImage.Width != sImage.Width) throw new Exception("Trời ảnh đâu có kích thước !"); else { BitmapData dabimage1 = inImage.LockBits(new Rectangle(0, 0, inImage.Width, inImage.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); BitmapData dabimage2 = sImage.LockBits(new Rectangle(0, 0, sImage.Width, sImage.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); int stretch = dabimage1.Stride; int offset = stretch - inImage.Width * 3; IntPtr scan0x = dabimage1.Scan0; IntPtr scan0y = dabimage2.Scan0; unsafe { byte* p = (byte*)(void*)scan0x; byte* q = (byte*)(void*)scan0y; int v;//bien so sanh gia tri cua pixel tuong ung for (int m = 0; m < inImage.Height; m++) { for (int n = 0; n < inImage.Width * 3; n++) { v = p[0] - q[0]; p[0]=(v image.Width) offset[x, y].X = image.Width; if (offset[x, y].Y < 0) offset[x, y].Y = 0; if (offset[x, y].Y > image.Height) offset[x, y].Y = image.Height ;.. . Matrix m = new Matrix(); m.TopLeft = 0; m.TopMid = -2; m.TopRight = 0; m.MidLeft = -2; m.Pixel = 11; m.MidRight = -2; m.BottomLeft = 0; m.BottomMid = -2; m.BottomRight = 0; m.Factor = Weight + 3 ;.. . offset[x, y].Y = y + bien; if (offset[x, y].X < 0) offset[x, y].X = 0; if (offset[x, y].X > image.Width) offset[x, y].X = image.Width; if (offset[x, y].Y < 0) offset[x, y].Y = 0; if (offset[x, y].Y >