1. Trang chủ >
  2. Công nghệ thông tin >
  3. Đồ họa >

Giới thiệu về xử lý ảnh

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (898.2 KB, 120 trang )


mấy quay kiểu ống là ví dụ điển hình cho dạng máy quét điện tử.

Từ khi công nghệ bán dẫn ra đời, các máy quay ảnh đợc sản xuất đã từng bớc

chiếm lĩnh thị trờng cả về mặt chất lợng cũng nh giá cả. Kết quả là các máy quét

kiểu Tube đợc a chuộng, các nhà chuyên môn và các khách hàng đều sử dụng

máy quét kiểu solid-state điển hình.

Tiền thân của máy quét solid-state sử dụng ngày nay là máy CCD (charged

coupled device), nó đợc phát minh bởi Williards Boyle Geoge Esmith tại

BellLabs vào những năm đầu của thập kỉ 70. Dựa trên các bộ cảm biến bán dẫn

máy quay CCD cảm nhận từng phần tử nhạy sáng riêng biệt, mỗi phần tử tơng

ứng với một điểm ảnh. Kích thớc của điểm thay đổi trong khoảng 7 tới 14 àm

(1àm =1x10-6 m). Trong khi đó bớc sóng của tia lazer He-Ne là 638 nm ,ánh

sáng đỏ (1 nm = 10-9 m). Trên hình 6.1 cho ta thấy hình ảnh của thang xám với

dọc trắng ở chính giữa.



Hình 6.1

Các máy quét điển hình ngày nay nhờ vào các phần tử CCD và kĩ thuật platen

mà có độ phân giải cao hơn các máy cầm tay. Hiện nay mọi ngời thờng chụp ảnh

bằng máy quay phim sau đó quét ảnh để đạt độ phân giải cao hơn. Phim ảnh thờng có độ rộng trung bình ( phim Kodak 3369 có độ rộng 35 mm) và đạt đợc

mật độ 100 dòng trên một mm(10000 nm), trong phòng thí nghiệm đạt đợc mật

độ 1000 dòng trên một mm (1000 nm)[ Kodak]. Những máy quét số có độ rộng

phim 35 mm cho 2048x3072 điểm, mỗi điểm cần tới 32 bits (muốn có thêm

thông

tin

hãy

liên

hệ

theo

địa

chỉ

http://www.davidmyes.com.au/rf8035.html .

Nh vậy mỗi một ảnh có khoảng 6.2 triệu điểm ảnh. Các máy quay điện tử sử

dụng CCD cho độ phân giải 850x984 điểm (ví dụ máy quét Video có sử dụng

CCD cho độ phân giải 640x480 điểm vói 24 bít màu cho một điểm ).

Mặc dù phim có độ phân giải cao hơn từ 10 đến 1000 lần trên một đơn vị ảnh

so với các máy quét CCD nhng một nhân tố hạn chế cơ bản là về kích thớc. Kích

thớc thông thờng của phim là 35 mm, nhng trong các trờng hợp khác đòi hỏi các

kích thớc lớn hơn ví dụ nh trong chiếu bóng phim 70mm, máy quay mô tả ảnh

động 127mm, phim X-quang, máy quay toàn cảnh ... thì gây rất nhiều khó khăn.

Tất nhiên khi kích thớc tăng lên thì số lợng các điểm ảnh cũng tăng. Một nhân tố

khác là giá cả, giá bán của các máy quay ảnh số thì giảm nhanh. Nh vậy con ngời không thấy thật cần thiết cần có ảnh độ phân giải cao do phim mamg lại mà

họ chỉ cần các ảnh tạo ra bởi các máy quay ảnh số.

Chúng ta nhận thấy có một số ngời phân vân không biết với phơng pháp

quét ảnh độ phân giải cao và kích thớc ảnh lớn thì cần bao nhiêu bộ nhớ. Chúng

ta hãy xét ví dụ sau, giả sử ta có một máy quét màu cho ảnh 3x5 inch vói 24 bit

cho một điểm ảnh, mỗi inch có 1200 điểm ảnh nh vậy sẽ có

83



3x5x1200x1200x3=64 MB(MB=megahyte, Mb=megabit). Nh vậy ngòi đó sẽ

tăng bộ nhớ lên 450MB khi chạy phần mềm PhotoShop và nh vậy cho phép quét

ảnh 8x10 với mật độ 1200 điểm /inch (8x10x1200x1200x3=345MB).

Sau đây chúng ta tìm hiểu một số phép xử lý đơn giản, các phép xử lý khác

đợc nói tới trong các phần tiếp theo. Trớc hết chúng ta bắt đầu với giao diện

Observer.



6.2 Giao diện Observer

Mặc dù giao diện Observer không đợc đa ra ở đây nhng nó là lớp trọng tâm

để tìm hiểu xem các hoạt động của lớp Image nh thế nào. Giao diện đặt trong gói

java.util (đây là gói th viện có sẵn của java) đợc sử dụng để thực thi các phơng

thức cần thiết và liên kết các thao tác trong môi trờng hớng đối tợng. Mối quan

hệ giữa lớp thi hành giao diện và lớp mở rộng là mối quan hệ kiểu modul-view.

Chúng ta hãy tởng tợng mối quan hệ modul-view tơng tự nh mối quan hệ giữa

bình ga ô tô và bộ phận đo nhiên liệu của nó. Khi lợng nhiên liệu trong bình ga

thay đổi thì bộ phận đo lợng nhiên liệu cho thấy sự thay đổi đó.

Sau đây ta xét hớng chảy thông tin giữa hai biến lớp, một biến là lớp mở

rộng của Observable biến còn lại là lớp thi hành giao diện Observer. Biến lớp

Obserable giữ một vector liệt kê tất cả các biến kiểu Observer, trong đó mỗi biến

kiểu Observerr thì lu trạng thái hoạt động của biến Observable. Mỗi khi biến

Observable có thay đổi nó gửi một bản cập nhật về các thông tin mới tới tất cả

các biến kiểu Observer đã đợc lu. Mối quan hệ này có dạng nh trên hình 6.2.



Hình 6.2



Nội dung của giao diện

package java.util;

public interface Observer {

void update(Observable o, Object arg);

}



Lớp Observable (the Observer Class)

Lớp Observer đặt trong gói java.util. Nh ta đã biết gói java.util là một

th viện chuẩn do java cung cấp, mỗi biến có kiểu Observable sử dụng một

84



instance của danh sách các biến Observer. Danh sách này gọi là ObserverList và

đặt trong gói java.util.



Tóm tắt nội dung của lớp

package java.util;

public class Observable {

public synchronized void addObserver(Observer o)

public synchronized void deleteObserver(Observer o)

public void notifyObserver()

public synchronized void notifyObservers(Object arg)

public synchronized void deleteObservers()

public synchronized boolean hasChanged()

public synchronized int countObservers()

}



Lớp NamedObservable

Lớp NamedObservable cung cấp một kĩ thuật liên kết một biến kiểu String

với một biến kiểu Observable.

package observers;

import java.util.*;

public abstract class NamedObservable extends Observable {

private String name;

public synchronized void setName(String nm) {

name = nm;

}

public synchronized String getName() {

return name;

}

}



Ví dụ về Observable Double và Observer-Observable

Chơng trình DiffCAD do ta viết cũng dựa trên dạng thức model-view và có

một gói tên là observers. Một trong các lớp thuộc gói Observers là lớp

ObservableDouble.

Khi phơng thức setValue đợc thực hiện với một biến thuộc kiểu

ObservableDouble thì phơng thức notifyObservers gọi tới phơng thức update để

gửi tới các biến có kiểu Observer những thay đổi đó.

package observers;

import java.util.*;

public class ObservableDouble extends NamedObservable {

private double value;

public ObservableDouble(double newValue, String nm) {

value = newValue;

setName(nm);

}

public synchronized void setValue(double newValue) {

if (newValue != value) {

value = newValue;

super.setChanged();

super.notifyObservers();

}

}

public synchronized double getValue() {

return value;

}



85



}



Lớp Image

Trong java, một ảnh đợc lu trong một instance của lớp Image, lớp này nằm

trong gói th viện chuẩn java.awt. Lớp Image đợc thiết lập với mục đích hình ảnh

sẽ đợc tạo ra bởi hệ thống có hạn chế I/O. Lớp Image cung cấp các phơng thức

thao tác với ImageObserver. Các biến có kiểu ImageObserver đợc lu giữ để thông

báo cho ngời dùng mỗi khi một hình ảnh mới đợc tạo ra.



Nội dung của lớp

package java.awt;

import java.awt.image.ImageProducer;

import java.awt.image.ImageObserver;

public abstract class Image {

public abstract int getWidth(ImageObserver observer);

public abstract int getHeight(ImageObserver observer);

public absteact ImageProducer getSource();

public abstract Graphics getGraphics();

public

abstract

Object

getProperty(String

name,

ImageObserver

observer);

public static final Observer UndefinedProperty = new Observer();

public abstract abstract void flush();

}



Cách sử dụng

Lớp Image sử dụng mô hình observer-observable và có thuộc tính abstract do

đó không thể khởi tạo nó trực tiếp. Giả sử ta khai báo các biến nh dới đây:

Image image;

ImageObserver imageObserver;

ImageProducer imageProducer;

int height, width;

Graphics graphics;

String name;



Khi đó muốn nhận đợc bề rộng của ảnh, bề cao của ảnh ta sử dụng các câu

lệnh sau:

width = image.getWidth(imageObserver);

height = image.getHeight(imageObserver);



Giá trị trả về sẽ là -1 nếu hình ảnh không tồn tại và thông báo Observer khi

hình ảnh đã hiện hữu.

Muốn nhận đợc biến mà biến này tạo ra các điểm ảnh:

imageProducer = image.getSource();



Để nhận đợc một biến đồ hoạ đối với hình ảnh off-screen :

graphics = image.getGraphics();



Để nhận đợc đặc tính của ảnh thông qua tên của ảnh.

object = image.getProperty(name, imageObserver);



nếu hình ảnh là không tồn tại, getproperty trả về giá trị null và thông báo cho

imageObserver ngay sau đó. Image.UndefinedProperty là một biến đối tợng

có thuộc tính static final đợc trả về khi đặc tính không đợc định nghĩa.

86



Cuối cùng để loại bỏ tất cả các nguồn sử dụng bởi hình ảnh mà hiện không

còn dùng tới ta sử dụng câu lệnh:

image.flush();



Giao diện ImageObserver

Giao diện ImageObserver nằm trong gói java.awt.image . Một instance

của lớp có bổ xung giao diện Imageobserver thì đợc xem nh trọng tâm trong nội

dung của một biến Imageproducer. Khi nội dung đợc thay đổi, biến

ImageObserver đợc thông báo cho biết có sự thay đổi đó nhờ vào lời gọi tới phơng thức inmageUpdate của Imagerproducer.



Nội dung của lớp

package java.awt.image;

import java.awt.Image;

public interface ImageObserver {

public boolean imageUpdate(Image img, int infoflags, int x, int y, int

width, int height);

public static final int WIDTH = 1;

public static final int HEIGHT = 2;

public static final int PROPERTIES = 4;

public static final int SOMEBITS = 8;

public static final int FRAMEBITS = 16;

public static final int ALLBITS = 32;

public static final int ERROR = 64;

public static final int ABORT = 128;



Ví dụ về ảnh trong ImageFrame

Lớp ImageFrame có phơng thức getImage tạo ra hộp hội thoại cho phép ngời

sử dụng nhập vào tên fie ảnh muốn xem, chờ quá trình đọc ảnh kết thúc và sau

đó tạo nguồn cần thiết để lu các biến ảnh này. Chúng ta cần nắm bắt cách thiết

kế này để phục vụ cho tác vụ đọc các file ảnh của ta. Dễ nhận thấy là các mã

lệnh rất khó cho việc hiểu, viết, và dạy hơn là một API đơn giản. Để tránh đ ợc

thì cách thông thờng là tạo ra một Imageproducer tạm trong đó có sử dụng phơng thức getImage. Phơng thức getImage khá thuận lợi cho ngời dùng, nhng

tổng quan mà nói ảnh đợc lu trên một thiết bị lu trữ ngầm và là nhỏ. Các biến

filename, image là các biến lớp thuộc lớp ImageFrame, phơng thức getImage có

dạng nh sau:

pulic void getImage() {

// Open the image by file name and wait for it!

Filename = Futil.getFileName();

System.out.println(Get image: +filename);

try{

image = getToolkit().getImage(filename);

waitForImage(this, name);

}

catch (Eception e) {

System.out.println(Get image could not open: + e);

}

//more the image, change its dimanetions

reshape(100,100,

image.getWidth(this), image.getHeight(this));

//set image title

setTitle(filename);

Show();



87



}



Hộp hội thoại có dạng nh sau:



Phơng thức waitForImage tránh lời gọi trở về và dừng các công việc trớc

khi phơng thức getImage đợc trả lại. Phơng thức paint của ImageFrame gọi tới

phơng thức drawImage có trong biến Graphics, g:

public void paint (Graphics g) {

g.drawImage(image, 0, 0, this);

}



Trong phần trên chúng ta đã tìm hiểu sơ lợc các phơng thức có sẵn của java

để thao tác với các file ảnh, sau đây là một số lớp do ta viết có sử dụng các tiện

ích sẵn có đó để thực hiện một số phép xử lý ảnh cơ bản.

Lớp ProcessPlane

Trong lớp ProcessPlane có ba phơng thức shadow, negate, edge nh sau:



Phơng thức negate

public void negate() {

int r,g,b,a;

for(int y =0; y
for(int x=0; x
r=getRed(x,y);

g=getGreen(x,y);

b=getBlue(x,y);

a=getAlpha(x, y);

setPixel(x,y,255-r,255-g,255-b,a);

}

}



phơng thức shadow

public void shadow() {

int r,g,b,a;

for(int y =0; y
for(int x=0; x
r=getRed(x,y);

g=getGreen(x,y);

b=getBlue(x,y);

a=getAlpha(x, y);



88



r=r + (127-getRed(x+2,y+2));

g=g + (127-getGreen(x+2,y+2));

b=b + (127-getBlue(x+2,y+2));

setPixel(x,y,r,g,b,a);

}

}



phơng thức edge:

public ProcessPlane edge() {

ProcessPlane pp = new ProcessPlane(getWidth(),

getHeight());

int r,a;

int average; // average intensity

for (int y = 0; y < getHeight(); y++)

new_line: {

average = 0;

for (int x =0 ; x < getWidth(); x++)

average = average + getRed (x,y);

average = average / getWidth();

for (int x =0 ; x < getWidth(); x++) {

r = getRed (x,y);

a = getAlpha(x,y);

if (r > average) {

int start=x;

for (int i=x;i < getWidth(); i++) {

r = getRed (i,y);

if (r < average) {

pp.setPixel(

start + (i - start) / 2,y,255,255,255,a);

break new_line;

}

}

}

}

}

return pp;

}



Sau đây là hiệu quả của ba phép xử lý trên:



89



Hiệu quả của phơng thức edge



Hiệu quả phơng thức shadow



Hiệu quả phơng thức negate



6.3 - ảnh số và Các dạng file ảnh



DATABAHN

Do số lợng ngời gia nhập vào Internet ngày càng nhiều nên thời gian nhận

dữ liệu từ một điểm A đến điểm B trên mạng sẽ kéo dài thêm. Từ trớc tới nay

chúng ta đều thực hiện nén nội dung thông tin trớc khi nó đợc truyền tới điểm

nhận. Một ảnh bitmap số không nén với 640x480, màu sắc 256 mầu thì cần 307

Kb, xấp xỉ một phần ba MB. Nh vậy sẽ tốn nhiều thời gian chờ để nạp file ảnh

này xuống browser của bạn từ một Web site nào đó trên mạng. Kích thớc lớn của

các ảnh số là động cơ thúc đẩy con ngời tìm ra các dạng nén file khác để nhằm

tiết kiệm bộ nhớ và thời gian truyền nhận.

Trong chơng này chúng ta bàn về cách tạo các dạng (format) ảnh-chúng đợc

biết nh là các kĩ thuật nén ảnh. Chúng ta sẽ tìm hiểu các kĩ thuật mới nhất hiện

đang đợc sử dụng trên mạng Internet.



Một số các dạng ảnh cơ bản

Trong phần này chúng ta nói đến một số dạng ảnh cơ bản: bitmap, vector và

các dạng khác.



BITMAP

Để mô tả một hình ảnh ta có thể áp dụng một số mức nén khác nhau. Mức

nén thấp nhất là mô tả ảnh dới dạng từng điểm ảnh đợc gọi là kĩ thuật

bitmapped- nó là một bản đồ các bit (điểm ảnh). ảnh bitmap và dữ liệu liên kết

với nó đợc thể hiện trên hình 6.3



90



Chú ý : Trong file tất cả dữ liệu bên đợc ghi tuân tự nh sau:

000000000100001110000100000000000000



Hình 6.3

Nhng vấn đề đặt ra là làm sao có thể hiện thị ảnh trên màn hình máy tính

hay màn hình TV. Màn hình là một mảng (array) giữ địa chỉ của các điểm ảnh

(còn gọi là dot), mỗi điểm đợc xác định vị trí bởi hai toạ độ và các thông tin về

mầu.

Các ảnh bitmap gây khó khăn cho việc cân bằng mầu, phân tích và truyền

dẫn bởi kích thớc của chúng là khá lớn. Tuy nhiên chúng ta có thể giải quyết một

phần nếu chúng ta sử dụng kĩ thuật nén tuy nhiên sẽ tốn nhiều thời gian để thực

hiện giải nén và hoàn trả lại ảnh nguyên thuỷ lúc ban đầu.



VECTOR

Bây giờ chúng ta hãy xem xét một kí thuật nén ảnh ở mức độ cao hơn. Giả sử

bạn lu điểm kết thúc của các đoạn thẳng biểu diễn một ảnh, có thể hoàn trả một

phác hoạ của CAD. Để xác định một đoạn thẳng ta cần lu điểm bắt đầu, hớng,

độ dài và mầu sắc. Phần nền không có các đoạn thẳng sẽ đợc trả lại với mầu của

nền hiển thị. Kiểu vector không chỉ lu các đoạn thẳng mà còn lu các hình thông

thờng khác nh hình tròn, hình vuông, các đa giác, đòng curred... với mức độ nén

cao hơn. Các hình này đợc tổ hợp với nhau để tạo nên các hình ảnh trên một bề

mặt nào đó. Trên hình 6.4 là một ví dụ đơn giản về hình ảnh kiểu vector và cách

lu dữ liệu của nó.

Một u điểm của của ảnh dới dạng vector là ta có thể dễ dàng cân bằng lại

ảnh mà không làm mất đi sự rõ nét của hình ảnh. Một nhợc điểm là dạng vector

khá cứng nhắc khi lu ảnh có độ rõ nét cao nh ảnh chụp, trong đó ta có thể dễ

dàng thay đổi thuộc tính mầu của từng điểm ảnh một.



Chuyển đổi giữa hai dạng Vector và Bipmap

Chuyển đổi từ dạng Vector sang dạng Bitmap thì đơn giản và cho phép thực

hiện trực tiếp. Việc đòi hỏi sự chuyển đổi là rất cần thiết bởi hầu hết các thiết bị

hiển thị đều cho phép hiển thị ảnh dới dạng bitmap. Đối với ảnh dạng Vector có

độ phân giải cao thì cần chọn lựa một giải pháp có độ phân giải cao để chuyển

sang dạng bitmap nhằm khắc phục đợc tối đa hiện tợng đờng thẳng bị biến dạng

thành đờng ziczac (jaggies).



Hình 6.4

91



Xem Thêm
Tải bản đầy đủ (.doc) (120 trang)

×