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