3.2.1. Giao diện chương trình
Dưới đây là giao diện của chương trình:
39
3.2.2. Chức năng thao tác với file ảnh
Hình 3.2. Form chức năng con thao tác với file ảnh a) Chức năng mở một file ảnh (Load ảnh)
+ File>>Open.
Khi chọn chức năng này, một cửa sổ dialog sẽ hiện ra cho phép tìm kiếm file ảnh cần load (mặc định là ổ C), sau khi tìm được file ảnh chọn ok và file sẽ được load lên form, từ đó có thể thực hiện nhiều phép xử lý tiếp theo với bức ảnh.
b) Chức năng lưu ảnh (Save) + File>>Save.
Tương tự như chức năng load ảnh, khi chọn chức năng lưu ảnh thì một cửa sổ dialog sẽ hiện ra cho phép chọn nơi lưu lại bức ảnh sau khi đã xử lý vào máy tính.
3.2.3. Chức năng chỉnh sửa
Chức năng “Undo”: Cho phép trở lại với thao tác xử lý gần nhất
40
3.2.4. Chức năng “Đổi màu ảnh”
Hình 3.4. Form chức năng đổi màu ảnh
Chức năng này cho phép thực hiện các xử lý ảnh đơn giản sử dụng toán tử điểm (thao tác trên từng pixel không liên quan đến các pixel lân cận). Bao gồm các chức năng con sau:
a) Tạo ảnh âm bản
Chức năng cho phép biến đổi từ một ảnh gốc thành một ảnh âm bản (ứng dụng lớn trong y học).
Hình 3.5. Form tạo ảnh âm bản b) Tạo ảnh đen trắng
Chức năng này cho phép biến đổi từ một ảnh gốc thành một ảnh đen trắng.
41
Hình 3.6. Form tạo ảnh đen trắng c) Màu theo độ sáng
Chức năng này cho phép thêm hoặc bớt giá trị màu thông qua các giá trị được nhập vào Parameter.
Hình 3.7. Form thay đổi độ sáng d) Màu được chỉnh theo độ tương phản
Chức năng này cho phép thêm hoặc bớt giá trị màu thông qua các giá trị được nhập vào Parameter.
Hình 3.8. Form thay đổi độ tương phản e) Chỉnh màu theo color: Bộ lọc màu sắc
Chức năng cho phépthêm hoặc bớt giá trị cho mỗi màu thông qua các giá trị được nhập vào ColorInput.
42
Hình 3.9. Form thay đổi màu sắc
3.2.5. Chức năng làm mịn ảnh
Là chức năng lọc nhiễu cho ảnh để tăng cường chất lượng của ảnh
Hình 3.10. Form chức năng làm mịn ảnh
3.2.6. Chức năng tìm biên ảnh
a) Thuật toán Sobell, Prewitt, Kirsh
Với chức năng này cho phép dò biên và làm nổi biên ảnh. Bao gồm các chức năng con:
Sobel:
Làm nổi biên ảnh theo kỹ thuật Gradient sử dụng toán tử Sobel.
Prewitt:
Làm nổi biên ảnh theo kỹ thuật Garadient sử dụng toán tử Prewith.
Kirsh:
43
Hình 3.11. Form chức năng tìm biên ảnh theo Sobell, Prewitt, Kirsh b) Tìm biên theo chiều ngang và dọc
Với chức năng này cho phép dò biên và làm nổi biên ảnh theo chiều ngang hoặc chiều dọc bằng phương pháp convolution.
Hình 3.12. Form chức năng tìm biên ảnh theo horizontal và vertical
3.2.7. Chức năng zoom ảnh
Chức năng này cho phép có thể phóng to hay thu nhỏ bức ảnh theo tỷ lệ cho (25%, 50%,100%....)
44
Hình 3.13. Form chức năng zoom ảnh
3.2.8.Chức năng biến dạng ảnh
a) Xoay ảnh
45 b) Xoay ảnh theo hình tròn
Hình 3.15. Form chức năng xoay ảnh theo hình tròn c) Biến dạng ảnh theo hình cầu lồi
Hình 3.16. Form chức năng biến dạng ảnh theo hình cầu lồi d) Biến dạng ảnh theo hình sóng nước
46
KẾT LUẬN VÀ HƯỚNG PHÁT TRIỂN
Hình ảnh là một dạng dữ liệu đóng vai trò quan trọng trong việc trao đổi, xử lý, lưu trữ thông tin…. Việc xử lý ảnh, tăng cường chất lượng hình ảnh nhằm loại bỏ nhiễu và hình ảnh sắc nét hơn là một vấn đề mà các nhà nghiên cứu đang rất quan tâm. Khóa luận tìm hiểu về một số kỹ thuật xử lý ảnh cơ bản và xây dựng chương trình mô phỏng đã đạt được những kết quả sau:
+ Khái niệm xử lý ảnh, những vấn đề cơ bản trong xử lý ảnh + Các định dạng ảnh cơ bản
+ Kỹ thuật sử dụng toán tử điểm + Kỹ thuật lọc nhiễu ảnh
+ Kỹ thuật phát hiện biên ảnh
+ Xây dựng được một chương trình mô phỏng các kỹ thuật xử lý ảnh với ảnh JPG và BMP.
Xây dựng chương trình mô phỏng việc xử lý hình ảnh bằng các kỹ thuật xử lý cơ bản như: kỹ thuật sử dụng toán tử điểm, lọc nhiễu ảnh và phát hiện biên ảnh nên cần tiếp tục mở rộng nghiên cứu phát triển thêm nhiều kỹ thuật xử lý ảnh phức tạp hơn, cho ra chất lượng hình ảnh tốt và giao diện dễ dàng sử dụng.
Khóa luận mới chỉ thực hiện được các kỹ thuật xử lý với ảnh JPG và BMP, do đó cần tiếp tục xây dựng chương trình để có thể xử lý với nhiều định dạng ảnh khác nhau.
Các kỹ thuật xử lý ảnh trình bày trong khóa luận đã ra đời từ nhiều năm trước do đó cần nghiên cứu những cải tiến đối với mỗi kỹ thuật để nâng cao việc xử lý chất lượng hình ảnh.
Mặc dù đã cố gắng rất nhiều nhưng vì thời gian có hạn và khả năng còn hạn chế nên chương trình chưa được thực sự như mong muốn. Em rất mong được sự đóng góp ý kiến của các thầy, cô giáo và các bạn để khóa luận của em được hoàn thiện hơn.
47
TÀI LIỆU THAM KHẢO
Các tài liệu Tiếng Việt
[1]. Lương Mạnh Bá, Nguyễn Thanh Thủy, Nhập môn xử lý ảnh số. Nxb. Khoa học và kỹ thuật, Hà Nội, 2002.
[2]. Đỗ Năng Toàn, Giáo trình xử lý ảnh. Học viện Công nghệ Bưu chính Viễn Thông, 2013.
[3]. Nguyễn Quang Hoan, Xử lý ảnh. Học viện Công nghệ Bưu chính Viễn Thông, 2006.
[4]. Nguyễn Chí Hướng, Lập trình một số bài toán cơ bản trong xử lý ảnh số. Đồ án tốt nghiệp chuyên ngành Tin học, Đại học Mỏ – Địa chất, 2010.
Các tài liệu Tiếng Anh
[5]. Dwayne Phillips. R&D Publications, 2000. Image Processing in C – Second Edition.
Các tài liệu từ Internet
48
PHỤ LỤC
1. Một số hàm và thủ tục chính 1.1. Mở một file ảnh
private void openToolStripMenuItem_Click(object sender,
EventArgs e) {
openFileDialog1.InitialDirectory = "C:\\";
openFileDialog1.Title = "Chọn File Ảnh";
openFileDialog1.Filter="Image File (*.bmp;*.jpg)|*.bm
p;
*.jpg|All File (*.*)|*.*";
openFileDialog1.RestoreDirectory = true;
if(openFileDialog1.ShowDialog()==DialogResult.OK)
{
bmp = new Bitmap(openFileDialog1.FileName);
this.AutoScroll = true;
this.AutoScrollMinSize = new Size((int)(bmp.Width
*
Zoom), (int)(bmp.Height*Zoo
m));
this.Invalidate();
}
}
1.2. Lưu file ảnh
private void saveToolStripMenuItem_Click(object sender,
EventArgs e) { saveFileDialog1.InitialDirectory = "C:\\"; saveFileDialog1.Filter = "Bitmap(*.bmp)|*.bmp| Jpeg File (*.jpg)|*.jpg"; saveFileDialog1.RestoreDirectory = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
bmp.Save(saveFileDialog1.FileName);
49
}
1.3. Hàm Undo ảnh
private void undoToolStripMenuItem_Click(object sender,
EventArgs e) {
Bitmap temp = (Bitmap)bmp.Clone(); bmp = (Bitmap)undo.Clone();
undo = (Bitmap)temp.Clone();
this.Invalidate();
}
1.4. Hàm thực hiện Zoom ảnh
Ví dụ với trường hợp hằng số zoom là 25%, các trường hợp khác tương tự.
private void toolStripMenuItem2_Click(object sender, Even tArgs
e)
{
Zoom = 0.25;
this.AutoScrollMinSize = new Size((int)(bmp.Width *
Zoom), (int)(bmp.Height * Zo
om));
this.Invalidate();
}
1.5. Hàm thực hiện lọc trung vị
public static bool Median(Bitmap b) {
Bitmap b1 = (Bitmap)b.Clone();
BitmapData bmdata = b.LockBits(new Rectangle(0, 0,
b.Width, b.Height),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
BitmapData b1data = b1.LockBits(new Rectangle(0, 0,
b.Width, b.Height),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
50
int stride2 = stride * 2;
ArrayList list; unsafe
{
byte* p = (byte*)bmdata.Scan0;
byte* p1 = (byte*)b1data.Scan0;
int nOffset = stride - b.Width * 3;
int nWidth = b.Width - 2;
//trừ đi các rìa ảnh
int nHeight = b.Height - 2;
int nPixel;
list = new ArrayList();
for (int y = 0; y < nHeight; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
for (int i = 0; i < 3; ++i) { list.Add(p1[0]); list.Add(p1[3]); list.Add(p1[6]); list.Add(p1[0 + stride]); list.Add(p1[3 + stride]); list.Add(p1[6 + stride]); list.Add(p1[0 + stride2]); list.Add(p1[3 + stride2]); list.Add(p1[6 + stride2]); list.Sort();
nPixel = Convert.ToInt32(list[4]);
if(nPixel<0) nPixel=0;
if(nPixel>255) nPixel=255;
p[3 + stride] = (byte)nPixel;
++p;
++p1;
51 } } p += nOffset; p1 += nOffset; } } b.UnlockBits(bmdata); return true; }
1.6. Hàm phát hiện và làm nổi biên + Theo phương pháp gradient
public static bool EdgedetectionConvolution(Bitmap b, sho rt
nType)
{
mask3x3 m = new mask3x3();
Bitmap btemp = (Bitmap)b.Clone(); switch (nType) { case EDGE_DETECT_SOBEL: m.SetAll(0); m.TopLeft = m.BotLeft = 1; m.TopRight = m.BotRight = -1; m.MidLeft = 2; m.MidRight = -2; break; case EDGE_DETECT_PREWITT: m.SetAll(0);
m.TopLeft = m.MidLeft = m.BotLeft = -1;
m.TopRight = m.MidRight = m.BotRight = 1;
break;
case EDGE_DETECT_KIRSH:
m.SetAll(-3);
m.pixel = 0;
m.TopLeft = m.MidLeft = m.BotLeft = 5;
52 } Image.ComplexFilter(b, m); switch (nType) { case EDGE_DETECT_SOBEL: m.SetAll(0); m.TopLeft = m.TopRight = 1; m.BotLeft = m.BotRight = -1; m.TopMid = 2; m.BotMid = -2; break; case EDGE_DETECT_PREWITT: m.SetAll(0);
m.BotLeft = m.BotMid = m.BotRight = -1;
m.TopLeft = m.TopMid = m.TopRight = 1;
break;
case EDGE_DETECT_KIRSH: m.SetAll(-3);
m.pixel = 0;
m.BotLeft = m.BotMid = m.BotRight = 5;
break; }
Image.ComplexFilter(btemp, m);
BitmapData bmdata = b.LockBits(new Rectangle(0, 0,
b.Width, b.Height), ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
BitmapData bmdata2 = btemp.LockBits(new Rectangle(0, 0,
b.Width, b.Height), ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
int Stride = bmdata.Stride;
unsafe {
byte* p = (byte*)bmdata.Scan0;
byte* p2 = (byte*)bmdata2.Scan0;
53
int nWidth = b.Width * 3;
int npixel = 0;
for (int y = 0; y < b.Height; ++y)
{
for (int x = 0; x < nWidth; ++x)
{
npixel = (int)Math.Sqrt((p[0] * p[0]
+ p2[0] * p2[0])); if (npixel < 0) npixel = 0; if (npixel > 255) npixel = 255; p[0] = (byte)npixel; ++p; ++p2; } p += nOffset; p2 += nOffset; } } b.UnlockBits(bmdata); btemp.UnlockBits(bmdata2); return true;
+Theo kỹ thuật Laplace
public static bool LaplaceH2(Bitmap b) {
mask3x3 m = new mask3x3(); m.SetAll(-1);
m.pixel = 8;
Image.ComplexFilter(b, m); return true;
}
+ Theo kỹ thuật gián tiếp
public static bool Giantiep(Bitmap b,int n) {
Bitmap b2 = (Bitmap)b.Clone();
BitmapData bmData = b.LockBits(new Rectangle(0, 0,
54
PixelFormat.Format24bppRgb);
BitmapData bmData2 = b2.LockBits(new Rectangle(0, 0,
b.Width, b.Height), ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
System.IntPtr Scan0 = bmData.Scan0;
System.IntPtr Scan02 = bmData2.Scan0;
unsafe {
byte* p = (byte*)(void*)Scan0;
byte* p2 = (byte*)(void*)Scan02;
int nOffset = stride - b.Width * 3;
int nWidth = b.Width * 3;
int nPixel = 0, nPixelMax = 0;
p += stride;
p2 += stride;
for (int y = 1; y < b.Height - 1; ++y)
{
p += 3;
p2 += 3;
for (int x = 3; x < nWidth - 3; ++x)
{
nPixelMax = Math.Abs(p2[0]
- (p2 + stride - 3)[0]);
nPixel = Math.Abs(p2[0] -
(p2 + stride)[0]);
if (nPixel > nPixelMax) nPixelMax = nPix
el;
nPixel = Math.Abs(p2[0]
- (p2 + stride + 3)[0]);
if (nPixel > nPixelMax) nPixelMax = nPix
55
nPixel = Math.Abs(p2[0] - (p2 -
stride)[0]);
if (nPixel > nPixelMax) nPixelMax = nPix
el;
nPixel = Math.Abs(p2[0] - (p2 - 3)[0]);
if (nPixel > nPixelMax) nPixelMax = nPix
el;
nPixel = Math.Abs(p2[0]
- (p2 - stride - 3)[0]);
if (nPixel > nPixelMax) nPixelMax = nPix
el;
nPixel = Math.Abs(p2[0] - (p2 + 3)[0]);
if (nPixel > nPixelMax) nPixelMax = nPix
el;
nPixel = Math.Abs(p2[0]
- (p2 - stride + 3)[0]);
if (nPixel > nPixelMax) nPixelMax = nPix
el; if (nPixelMax < n) nPixelMax = 0; p[0] = (byte)nPixelMax; ++p; ++p2; } p += 3 + nOffset; p2 += 3 + nOffset; } } b.UnlockBits(bmData); b2.UnlockBits(bmData2);
56
return true; }