Tải bản đầy đủ (.pdf) (94 trang)

TÀI LIỆU XỬ LÝ ẢNH (OPENCVPYTHON) ĐẦY ĐỦ NHẤT

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 (5.24 MB, 94 trang )

CHƯƠNG 1: KỸ THUẬT BIẾN ĐỔI ẢNH SỐ CƠ BẢN
1.1. Giới thiệu
1.1.1. Kiến thức cơ bản
a. Ảnh kĩ thuật số (Digital image)
b. Độ phân giải của ảnh (Resolution)
c. Điểm ảnh (Pixel)
d. Mức xám của ảnh (Grayscale)
e. Ảnh màu
1.1.2. Hướng dẫn lập trình OpenCV-Python
1.2. Lập trình các phép biến đổi cơ bản của ảnh
1.2.1. Các phép xuất nhập ảnh và video
a. Đọc - hiển thị ảnh và ghi ảnh trong OpenCV
b. Hiển thị ảnh bằng matplotlib
c. Mở - lưu từ camera và phát video
1.2.2. Các phép biến đổi và vẽ hình cơ bản
a. Vẽ hình cơ bản
b. Các phép biến đổi cơ bản
1.2.3. Các phép toán đại số trên ảnh
1.2.4. Các phép tốn logic trên ảnh
1.3. Lập trình các phép tốn tiền xử lý ảnh
1.3.1. Lọc ảnh là gì
1.3.2. Nguyên lý hoạt động của lọc ảnh
1.3.3. Lọc chập (Convolution)
1.3.4. Làm mờ ảnh (Blur)
1.3.5. Lập trình ứng dụng các phép lọc ảnh
a. Lọc tuyến tính
b. Biến đổi Fourier
1.3.6. Các phép nổi biên
a. Hàm sử dụng
b. Lọc Laplace và Sobel làm nổi biên
c. Biến đổi ảnh Pyramids




1.3.7. Các phép biến đổi hình thái học
1.4. Bài tập áp dụng

CHƯƠNG 2: TRÍCH RÚT ĐẶC TRƯNG
2.1. Phân đoạn theo biên ảnh
2.1.1. Giới thiệu phân đoạn ảnh
2.1.2. Một vài ứng dụng cụ thể trong phân vùng ảnh
2.1.3. Thuật toán phân vùng ảnh sử dụng hàm tìm đường đồng mức (Contours)
2.1.4. Bài tập mở rộng
2.2. Phân đoạn ảnh theo ngưỡng
2.2.1. Phân vùng theo ngưỡng biên độ
a. Dựa vào đặc tính vật lý của ảnh, có nhiều kỹ thuật phân vùng
b. Việc chọn ngưỡng rất quan trọng, gồm các bước
c. Ví dụ
2.2.2. Phân vùng ảnh bằng cách khoanh vùng với đường bao nhỏ nhất
2.2.3. Bài tập mở rộng
2.3. Phân đoạn ảnh theo màu đồng nhất
2.3.1. Giới thiệu
2.3.2. Phân đoạn dùng thuật toán watershed
2.3.3. Phân đoạn loại nền dùng thuật toán grabCut
a. Giới thiệu
b. GrabCut Foreground
c. Hướng dẫn
2.3.4. Thuật toán grabCut
2.3.5. Phát hiện góc (Corner Detection )
a. Tìm góc cạnh dùng thuật tốn Shi-Tomasi
2.3.6. Bài tập mở rộng
2.4. Trích chọn đặc trưng ảnh

2.4.1. Trích chọn đặc trưng dùng thuật tốn SIFT (Scale-Invariant Feature
Transform)
a. Các bước thực hiện thuật toán SIFT


b. Phát hiện các điểm cực trị Scale-Space
c. Định vị điểm nổi bật
d. Xác định hướng cho các điểm nổi bật
e. Mơ tả các điểm nổi bật
2.4.2. Thuật tốn SIFT
2.5. Bài tập áp dụng
a. Rút trích đặc trưng ảnh
b. Tìm đường bao ảnh
c. Cắt ảnh loại bỏ nền sử dụng mặt nạ

CHƯƠNG 3: PHÁT HIỆN ĐỐI TƯỢNG
3.1. Hiệu chuẩn camera
3.1.1. Hiệu chuẩn webcam
3.1.2. Thuật tốn chuẩn hóa camera
3.2. Lập trình ứng dụng tìm xác định đối tượng trên ảnh
3.2.1. Xác định trọng tâm và đường bao của blob trên ảnh
a. Blob là gì?
b. Hoạt động để phát hiện Blob
c. Lọc Blobs theo màu sắc, kích thước và hình dạng
3.2.2. Thuật toán xác định trọng tâm blob trên ảnh
3.2.3. Thuật toán xác định trọng tâm và đường bao blob trên ảnh
3.3. Phát hiên đối tượng dùng biến đổi Hough
3.3.1. Phát hiện đường thẳng dùng phương pháp houghline
3.3.2. Khái niệm cơ bản về phương pháp Houghline
3.3.3. Hoạt động của phương pháp Houghline

3.3.4. Thí dụ về biến đổi Hough
3.3.5. Các ứng dụng của biến đổi Hough
3.3.6. Thuật toán biến đổi Hough
3.3.7. Bài tập mở rộng
3.4. Khôi phục ảnh
3.4.1. Khôi phục ảnh bằng cách khử nhiễu


3.4.2. Kỹ thuật khôi phục ảnh Inpainting
3.4.3. Khôi phục ảnh HDR (High Dynamic Range)
3.5. Bài tập áp dụng

CHƯƠNG 4: NHẬN DẠNG ĐỐI TƯỢNG
4.1. Nhận dạng sự giống nhau ảnh dùng phương pháp ánh xạ ảnh
4.1.1. Giới thiệu về nhận dạng đối tượng
4.1.2. Ánh xạ ảnh
4.1.3. Nhận dạng theo phương pháp ánh xạ Brute force với mô tả đặc trưng ORB
4.1.4. Ánh xạ theo mô tả đặc trưng SIFT
4.1.5. Bài tập mở rộng
4.2. Nhận dạng đối tượng theo đường hình học
4.2.1. Nhận dạng theo đường hình học Epipolar
4.2.2. Xoay ảnh dựa vào đặc trưng cơ bản
4.2.3. Bài tập mở rộng
4.3. Nhận dạng đối tượng theo cấu trúc
4.3.1. Nhận diện gương mặt sử dụng Haar-cascade trên OpenCV

CHƯƠNG 5: PHÁT HIỆN ĐỐI TƯỢNG
5.1. Giới thiệu phân tích dữ liệu và nhận dạng mẫu
5.1.1. Nhận dạng mẫu
5.1.2. Thuật tốn k-NN

5.2. Tìm và phát hiện chuyển động của đối tượng
5.3. Tìm và phát hiện chuyển động theo hình học lập thể
5.3.2. Thuật tốn xác định độ sâu ảnh
5.4. Thuật toán khử nhiễu cục bộ để loại bỏ nhiễu trong ảnh
5.4.1. Giới thiệu hàm khử nhiễu cục bộ
5.4.2. Thuật toán loại nhiễu cục bộ


KỸ THUẬT BIẾN ĐỔI ẢNH SỐ CƠ BẢN
1.1. Giới thiệu
1.1.1.

Kiến thức cơ bản

a. Ảnh kĩ thuật số (Digital image)
Ảnh kĩ thuật số (digital image) là một dạng biểu diễn của ảnh ở dạng ma trận số 2 chiều.
Tùy vào độ phân giải của ảnh có cố định hay khơng, ảnh kĩ thuật số được chia ra làm 2 loại là
ảnh vector (độ phân giải không cố định) và ảnh raster (hay còn gọi là bitmapped, độ phân giải
cố định). Thuật ngữ ảnh kĩ thuật số thường được dùng để nói đến ảnh raster.

b. Độ phân giải của ảnh (Resolution)
Độ phân giải ảnh là mức độ chi tiết mà ảnh có thể thể hiện. Thuật ngữ này được dùng cho
ảnh raster. Độ phân giải càng cao, ảnh càng nhiều chi tiết. Ví dụ: độ phân giải 640 x 480.

c. Điểm ảnh (Pixel)
Trong ảnh kĩ thuật số, một điểm ảnh (pixel) là phần tử nhỏ nhất của ảnh raster (raster
image). Mỗi một điểm ảnh là một mẫu (sample) của ảnh. Càng nhiều điểm ảnh, ảnh kĩ thuật số
càng biểu diễn chính xác hơn về nội dung của ảnh gốc. Đặc trưng của một điểm ảnh gồm 2
thành phần: tọa độ (x,y) và cường độ sáng (intensity).


d. Mức xám của ảnh (Grayscale)
Mức xám của ảnh (greyscale) là một trong những giá trị số của điểm ảnh biểu diễn mức
độ ánh sáng (light intensity) tại điểm ảnh đó. Thơng thường, trong xử lý ảnh hiện tại, mức xám
hay sử dụng nhất là mức 256 (có giá trị mức xám từ 0 → 255).

e. Ảnh màu
Để biểu diễn ảnh màu, theo cách biểu diễn RGB, ba ma trận mức xám 256, ứng với ba
màu đỏ (R), lục (G), lam(B) được sử dụng. Màu sắc của một điểm ảnh được quyết định bởi giá
trị cường độ (intensity) tại ba ma trận màu cùng tọa độ.

1.1.2.

Hướng dẫn lập trình OpenCV-Python

Để có thể lập trình ứng dụng OpenCV vào thị giác máy tính ta cần hiểu lệnh, hàm, thư
viện… trong OpenCV, sau đây là một chương trình đơn giản dùng ngôn ngữ python sử dụng
thư viện OpenCV.
1


import cv2
img = cv2.imread('MyPictures/opencv-logo.png', 1)
cv2.imshow('example', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

− import cv2: Để sử dụng được OpenCV, bước đầu tiên, ta cần phải khai báo thư
viện OpenCV bằng dòng lệnh import cv2.
− imread: Để đọc ảnh từ file vào, OpenCV đã hỗ trợ hàm imread với tham số đầu
vào là đường dẫn đến file và chế độ màu của ảnh 0 là ảnh xám còn 1 là ảnh màu.

− imshow: Để hiển thị ảnh ngồi màn hình, ta có thể sử dụng hàm imshow do
OpenCV hỗ trợ với tham số thứ nhất là tên cửa sổ ảnh và tham số thứ hai là nội
dung ảnh.
− cv2.waitKey(0): Sau khi hiển thị nội dung ảnh, bằng lệnh cv2.waitKey(0),
chương trình sẽ chờ cho đến khi người dùng nhấn một phím bất kì rồi mới thốt
khỏi chương trình.
− cv2.destroyAllWindows(): Xóa tất cả các cửa sổ nhưng khơng tạo ra bất kỳ sự
thay đổi nào trong code này. Các cửa sổ sẽ bị xóa do code đã hồn thành việc thực
thi, nhưng nếu chúng ta có một chương trình lớn hơn và sau đó có một số dịng
code khác đang chạy, thì các cửa sổ vẫn được mở. Vì vậy, nó ln ln được đặt
vào cuối chương trình

1.2. Lập trình các phép biến đổi cơ bản của ảnh
1.2.1.

Các phép xuất nhập ảnh và video

a. Đọc - hiển thị ảnh và ghi ảnh trong OpenCV
• Hàm sử dụng
retval=cv.imread(filename[, flags])
retval, mats=cv.imreadmulti(filename[, mats[, flags]])

• Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import numpy as np
import cv2
img = cv2.imread('MyPictures/opencv-logo.png', cv2.IMREAD_GRAYSCALE)
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', img)
k = cv2.waitKey(0)
if k == 27:


2


cv2.destroyAllWindows()
elif k == ord('s'):
cv2.imwrite('opencv_logo_gray.png', img)
cv2.destroyAllWindows()

• Bài tập mở rộng
− Dựa vào code mẫu trên hãy khảo sát lại các lệnh để đưa ra kết quả và nhận xét sự
khác biệt
+

Trong lệnh imread()
cv2.IMREAD_GRAYSCALE thay
cv2.IMREAD_COLOR, cv2.IMREAD_UNCHANGED

Chú ý tìm hiểu cách thay thế 0, 1, -1
+ Trong lệnh namedWindow()
cv2.WINDOW_NORMAL thay
cv2.WINDOW_AUTOSIZE, cv2.WINDOW_KEEPRATIO
− Tìm hiểu thêm các câu lệnh sau và thực hiện chương trình như kết quả
img = cv2.resize(img, (640, 480))
rows,cols,ch=img.shape
print('row/col:',rows,'Column/width:',cols,'aisle:',ch)
retval2,threshold2=cv2.threshold(grayscaled,125,255,
cv2.THRESH_OTSU);

cv2.THRESH_BINARY+


Thay các hàm cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV
cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;
cv2.THRESH_OTSU và kết hợp 2 hàm với nhau

cv2.THRESH_TOZERO_INV,

th=cv2.adaptiveThreshold(grayscaled,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 115, 1)
Thay các hàm cv2.ADAPTIVE_THRESH_MEAN_C
→ Nhận xét kết quả khi thêm và thay các lệnh và các hàm trên

b. Hiển thị ảnh bằng matplotlib
• Hàm sử dụng
3


− Cách thứ nhất
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
plt.xticks([]), plt.yticks([]) # to hide tick values on X and Y axis
plt.show()


Cách thứ hai
plt.subplot(231), plt.imshow(img1, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')

plt.show()



Cách thứ ba
axes[0].imshow(img)
axes[0].set_title('origin')
axes[1].imshow(edge_img)
axes[1].set_title('result')
plt.show()

• Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
− Code 1
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-20, 20, 1000)
y = x * x
plt.plot([-4, -3, -2, -1, 0, 1, 2, 3, 4], [16, 9, 4, 1, 0, 1, 4, 9, 16])
plt.plot(x, y)
plt.show()
plt.show(x,y)

− Code 2
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('MyPictures/drawing.png',0)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
plt.xticks([]), plt.yticks([])
plt.show()


• Bài tập mở rộng
− Dựa vào code mẫu trên hãy khảo sát lại các lệnh để đưa ra kết quả về sự khác
biệt
+ Áp dụng lại với các hàm ngưỡng và ngưỡng thích nghi ở mục a để kiểm tra lại
+ Sử dụng thêm các hàm mới sau
4


M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(img, M, (300, 300))
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 45, 0.6)
res = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)
→ Nhận xét kết quả khi thêm và thay các lệnh và các hàm trên

c. Mở - lưu từ camera và phát video
• Hàm sử dụng
− Mở camera
cap = cv.VideoCapture(0)


Phát video
cap = cv.VideoCapture('vtest.avi')

− Lưu video từ camera
fourcc = cv.VideoWriter_fourcc(*'XVID')
out = cv.VideoWriter('output.avi',fourcc, 20.0, (640,480))

• Mở camera
− Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh

import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
while(True):
ret, frame = cap.read()
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
cv.imshow('frame',gray)
if cv.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv.destroyAllWindows()

− Bài tập mở rộng
frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
frame_height=int(480/frame_width*frame_height)
ret = cap.set(cv2.CAP_PROP_FRAME_HEIGHT, frame_height)

ret = cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)

5


− Sinh viên tìm hiểu để thay đổi chương trình sao cho camera hiển thị ảnh màu với
kích thước khung ảnh giá trị khác (320x240)
→ Nhận xét kết quả khi thêm và thay các lệnh và các hàm trên

• Lưu video từ camera
− Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import numpy as np

import cv2 as cv
cap = cv.VideoCapture(0)
fourcc = cv.VideoWriter_fourcc(*'XVID')
out = cv.VideoWriter('output.avi',fourcc, 20.0, (640,480))
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
frame = cv.flip(frame,0)
out.write(frame)
cv.imshow('frame',frame)
if cv.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
out.release()
cv.destroyAllWindows()

− Bài tập mở rộng
+ Thay đổi code sao cho ảnh quay thuận và ngược trên màn hình
+ Tìm hiểu cách thay đổi để lưu video dưới phần mở rộng khác *.avi
+ Tìm hiểu các lệnh mới áp dụng vào code trên
frame = cv2.resize(frame, (width, height))
→ Nhận xét kết quả khi thêm và thay các lệnh và các hàm trên

• Phát video
− Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import numpy as np
import cv2 as cv
cap = cv.VideoCapture('MyPictures/vtest.avi')

while(cap.isOpened()):

6


ret, frame = cap.read()
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
cv.imshow('frame',gray)
if cv.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv.destroyAllWindows()

− Bài tập mở rộng
+ Sinh viên áp dụng hàm plt để hiển thị
+ Phát video bằng cách đọc frame
fps = cap.get(cv2.CAP_PROP_FPS)
frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
FRAME_NOW = cap.get(cv2.CAP_PROP_POS_FRAMES)
→ Nhận xét kết quả khi thêm và thay các lệnh và các hàm trên

1.2.2.

Các phép biến đổi và vẽ hình cơ bản

a. Vẽ hình cơ bản
• Hàm sử dụng
cv.CreateTrackbar(trackbarName, windowName, value, count, onChange) → None
retval=cv.getTrackbarPos(trackbarname, winname) → retval

img = np.zeros((512,512,3), np.uint8)
img=cv.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]])
img=cv.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]])
img=cv.circle(img, center, radius, color[, thickness[, lineType[, shift]]])
img=cv.ellipse(img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]])
img=cv.ellipse(img, box, color[, thickness[, lineType]])
img=cv.polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]])
img=cv.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]])

• Tạo Trackbar
− Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import numpy as np
import cv2 as cv
def nothing(x):
pass
img = np.zeros((300,512,3), np.uint8)
cv.namedWindow('image')
cv.createTrackbar('R','image',0,255,nothing)

7


cv.createTrackbar('G','image',0,255,nothing)
cv.createTrackbar('B','image',0,255,nothing)
switch = '0 : OFF \n1 : ON'
cv.createTrackbar(switch, 'image',0,1,nothing)
while(1):
cv.imshow('image',img)
k = cv.waitKey(1) & 0xFF
if k == 27:

break
r = cv.getTrackbarPos('R','image')
g = cv.getTrackbarPos('G','image')
b = cv.getTrackbarPos('B','image')
s = cv.getTrackbarPos(switch,'image')
if s == 0:
img[:] = 0
else:
img[:] = [b,g,r]
cv.destroyAllWindows()

− Bài tập mở rộng
Tìm hiểu lệnh sau cv2.getTrackbarPos(). Xem hàm thay đổi chế độ mode = True và
hàm gọi lại mouse

• Tạo ảnh đen và trắng
− Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import numpy as np
import cv2
size = (2560, 1600)
black = np.zeros(size)
print(black[34][56])
cv2.imwrite('black.jpg',black)
black[:]=255
print(black[34][56])
cv2.imwrite('white.jpg',black)

− Bài tập mở rộng: thực hiện kết quả như gợi ý
im = Image.new("RGB", (128, 128))
pix = im.load()

for x in range(128):
for y in range(128):
pix[x,y] = (255,0,0)
im[:,:,:] = (255,0,0)

• Các hàm vẽ hình cơ bản
8


− Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import numpy as np
import cv2 as cv
img = np.zeros((512,512,3), np.uint8)
cv.line(img,(0,0),(511,511),(255,0,0),5)
cv.rectangle(img,(384,0),(510,128),(0,255,0),3)
cv.circle(img,(447,63), 63, (0,0,255), -1)
cv.ellipse(img,(256,256),(100,50),0,0,180,255,-1)
pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
pts = pts.reshape((-1,1,2))
cv.polylines(img,[pts],True,(0,255,255))
font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),2,cv.LINE_AA)
cv.imshow('image',img)
cv.waitKey(0)
cv.destroyAllWindows()

− Bài tập mở rộng: thực hiện kết quả như gợi ý
cv2.setMouseCallback("Canvas", click_event)
radius = np.random.randint(5, high=200)
color = np.random.randint(0, high=256, size=(3,)).tolist()

pt = np.random.randint(0, high=300, size=(2,))
cv2.circle(canvas, tuple(pt), radius, color, -1)

b. Các phép biến đổi cơ bản
• Hàm sử dụng
b,g,r = cv.split(img)
img = cv.merge((b,g,r))
dst=cv.cvtColor(src, code[, dst[, dstCn]])
dst=cv.applyColorMap(src, colormap[, dst])
dst=cv.applyColorMap(src, userColor[, dst])
dst=cv.AddWeighted(src1, alpha, src2, beta, gamma, dst)
hist=cv.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
plt.hist(img.ravel(),256,[0,256]); plt.show()
dst=cv.equalizeHist(src[, dst])

• Tách và kết hợp màu: (Splitting and Merging Image Channels)


Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import numpy as np
import cv2 as cv
img = cv.imread('MyPictures/messi5.jpg')
b,g,r = cv.split(img)
img = cv.merge((b,g,r))
img[:,:,2] = 0
cv.imshow('Image',img)
cv.waitKey(0)

9



cv.destroyAllWindows()

• Biến đổi khơng gian màu
− Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
img=cv2.imread('MyPictures/messi5.jpg')
cv2.imshow("RGB",img)
img_HSV = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
cv2.imshow("HSV",img_HSV)
cv2.waitKey(0)

− Thực hiện code sau để tìm tất cả khơng gian màu
import cv2
from pprint import pprint
flags = [i for i in dir(cv2) if i.startswith('COLOR_')]
pprint(flags)

− Chọn khơng gian màu vừa tìm và thay đổi khơng gian màu quen thuộc vào code
mẫu để in ra 10 không gian màu khác nhau

• Tạo bản màu
− Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
def colormap_name(id) :
switcher = {
0 : "COLORMAP_AUTUMN",
1 : "COLORMAP_BONE",

2 : "COLORMAP_JET",
3 : "COLORMAP_WINTER",
4 : "COLORMAP_RAINBOW",
5 : "COLORMAP_OCEAN",
6 : "COLORMAP_SUMMER",
7 : "COLORMAP_SPRING",
8 : "COLORMAP_COOL",
9 : "COLORMAP_HSV",
10: "COLORMAP_PINK",
11: "COLORMAP_HOT"
}
return switcher.get(id, "NONE")
if __name__ == '__main__' :
im = cv2.imread("MyPictures/pluto.jpg", cv2.IMREAD_GRAYSCALE)
im_out = np.zeros((600, 800, 3), np.uint8);

10


for i in range(0,4) :
for j in range(0,3) :
k = i + j * 4
im_color = cv2.applyColorMap(im, k)
cv2.putText(im_color, colormap_name(k), (30, 180),
cv2.FONT_HERSHEY_DUPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA);
ix200 = i * 200
jx200 = j * 200
im_out[ jx200 : jx200 + 200 , ix200 : ix200 + 200 , : ] =
im_color
cv2.imshow("Pseudo Colored", im_out);

cv2.waitKey(0);

− Sinh viên viết chương trình xác định giá trị màu của 4 khơng gian màu theo vị trí
chuột trên màm hình như kết quả gợi ý

• Trộn ảnh
− Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
from matplotlib import pyplot as plt
img1 = cv2.imread('MyPictures/ml.png')
img2 = cv2.imread('MyPictures/opencv_logo.png')
dst = cv2.addWeighted(img1,0.7,img2,0.3,0)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

− Sinh viên viết chương trình trộn ảnh có sử dụng kênh alpha như kết quả gợi ý

• Vẽ histogram
11




Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('MyPictures/home.jpg', 0)

plt.hist(img.ravel(), 256, [0, 256])
plt.show()



Sinh viên viết chương trình vẽ histogram như kết quả gợi ý

• Cân bằng Histogram


Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('MyPictures/wiki.jpg',0)
equ = cv.equalizeHist(img)
res = np.hstack((img,equ))
cv.imwrite('res.png',res)
cv.imshow('Res',res)
cv.waitKey(0)
cv.destroyAllWindows()

− Sinh viên viết chương trình cân bằng và vẽ histogram như kết quả gợi ý

12


1.2.3.

Các phép toán đại số trên ảnh


a. Hàm sử dụng
dst=cv.add( src1, src2[, dst[, mask[, dtype]]])
dst=cv.subtract(src1, src2[, dst[, mask[, dtype]]])
dst=cv.multiply(src1, src2[, dst[, scale[, dtype]]])
dst=cv.divide(src1, src2[, dst[, scale[, dtype]]])
dst=cv.divide(scale, src2[, dst[, dtype]])
dst=cv.pow(src, power[, dst])
dst=cv.sqrt(src[, dst])

b. Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
img1=cv2.imread('MyPictures/subtract1.jpg',0)
img2=cv2.imread('MyPictures/subtract2.jpg',0)
cv2.imshow('subtract1',img1)
cv2.imshow('subtract2',img2)
st=img2-img1
cv2.imshow('after subtract',st)
ret,threshold=cv2.threshold(st, 50,255, cv2.THRESH_BINARY)
cv2.imshow('after threshold', threshold)
cv2.waitKey(0)

c. Bài tập mở rộng
− Thực hiện các phép toán : +, *, /, //, **
− Thực hiện phép toán dùng các hàm như gợi ý
cv2.subtract, cv2.add, cv2.multiply, cv2.divide, cv2.pow, cv2.sqrt
− Thay đổi hàm ngưỡng để tìm kết quả tốt nhất cho từng trường hợp ảnh xám và
ảnh màu


1.2.4.

Các phép toán logic trên ảnh

a. Hàm sử dụng
dst=cv.bitwise_not(src [, dst[, mask]])
dst=cv.bitwise_or(src1, src2[, dst[, mask]])
dst=cv.bitwise_xor(src1, src2[, dst[, mask]])
dst=cv.bitwise_and(src1, src2[, dst[, mask]])

b. Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
img1=cv2.imread('MyPictures/subtract1.jpg',0)
img2=cv2.imread('MyPictures/subtract2.jpg',0)

13


cv2.imshow('subtract1',img1)
cv2.imshow('subtract2',img2)
st=cv2.bitwise_and(img1, img2)
cv2.imshow('after subtract',st)
ret,threshold=cv2.threshold(st, 50,255, cv2.THRESH_BINARY)
cv2.imshow('after threshold', threshold)
cv2.waitKey(0)

c. Bài tập mở rộng
− Thực hiện các phép toán logic như gợi ý
cv2.bitwise_or, cv2.bitwise_xor, cv2.bitwise_not


− Thay đổi hàm ngưỡng để tìm kết quả tốt nhất cho từng trường hợp
− Thực hiện lại kết quả trên với ảnh màu

1.3. Lập trình các phép tốn tiền xử lý ảnh
1.3.1.

Lọc ảnh là gì

Lọc ảnh là một kĩ thuật chỉnh sửa hoặc làm rõ ảnh. Việc loại bỏ những điểm lốm đốm
trên một bức ảnh cũ, hay làm nét một bức ảnh bị nhòe, đấy là một số ví dụ về ứng dụng của
việc lọc ảnh. Làm mịn hay mờ ảnh, làm nét ảnh hay làm sắc nét cạnh của ảnh là một số phép
xử lý ảnh phổ biến của Lọc ảnh.

1.3.2.

Nguyên lý hoạt động của lọc ảnh

Lọc là phép toán thực hiện biến đổi một điểm ảnh dựa trên thông tin của các điểm ảnh
xung quanh điểm ảnh đó. Nói một cách đơn giản, khi chúng ta đưa một điểm ảnh vào, Lọc sẽ
lấy thông tin của điểm ảnh lân cận tức những con số về cường độ sáng, áp dụng cơng thức tốn
để tính ra giá trị đầu ra của điểm ảnh đấy.
Thông thường, trong xử lý ảnh, các công thức dùng để biến để giá trị thường ở dạng tuyến
tính. Cơng thức tuyến tính là cơng thức có dạng a1x1 + a2x2 + ... + anxn=0) Và để thực hiện việc
tính tốn một cách nhanh chóng, cơng thức biến đổi sẽ được biểu diễn thành một ma trận
nhân/lõi (kernel/mask/convolution matrix), và việc biến đổi ảnh sẽ được thực hiện bằng cách
tính tích chập giữa ma trận nhân.

Hình 1.1: Lọc ảnh
14



1.3.3.

Lọc chập (Convolution)

Trong tốn học, Convolution (tích chập) là một phép toán với đầu vào là 2 hàm số (hàm
f và g), với kết quả đầu ra là một hàm mới được tạo từ 2 hàm f và g. Đối với bài tốn xử lý ảnh,
ta có thể coi:


Hàm f: ảnh đầu vào



Hàm g: ma trận nhân kernel



Kết quả Convolution (f*g): ảnh sau khi biến đổi
Cơng thức tính Convolution (1D) được định nghĩa như sau:

Đối với bài toán xử lý ảnh, chúng ta sẽ áp dụng cơng thức tính Convolution 2D (sau khi
đã lấy mẫu đưa về dạng rời rạc):
+∞

+∞

𝑦[𝑚, 𝑛] = 𝑥[𝑚, 𝑛] ∗ ℎ[𝑚, 𝑛] = ∑ ∑ 𝑥[𝑖, 𝑗]. ℎ[𝑚 − 𝑖, 𝑛 − 𝑗]
𝑗=−∞ 𝑖=−∞


Áp dụng cơng thức trên vào, ta có kết quả như hình dưới
Như hình trên, mục tiêu của phép convolution này là tính giá trị mới của e (tọa độ [2,2])
sau khi biến đổi. Theo cơng thức tính Convolution 2D, ta có:
f∗g([2,2])=f([2,2])∗g([2,2])f∗g([2,2])=f([2,2])∗g([2,2])
(Chú ý: Phép * ở đây là phép Convolution, không phải phép nhân thơng thường)
=f[1,1].g[4−1,4−1]+f[1,2].g[4−1,4−2]+f[1,3].g[4−1,4−2]+=f[1,1].g[4−1,4−1]+f[1,2].g[4
−1,4−2]+f[1,3].g[4−1,4−2]+f[2,1].g[4−2,4−1]+...+f[3,3].g[4−3,4−3]f[2,1].g[4−2,4−1]+.
..+f[3,3].g[4−3,4−3] =a.9+b.8+c.7+d.6+...+i.1=a.9+b.8+c.7+d.6+...+i.1

1.3.4.

Làm mờ ảnh (Blur)

Trước khi nói về cách làm mờ ảnh, chúng ta sẽ nói về vấn đề tại sao phải làm mờ ảnh.

Hình 1.2 Ví dụ ảnh nhiễu
15


Hình bên trên là một ví dụ minh họa cho ảnh bị nhiễu. Một cách trực quan, chúng ta có
thể định nghĩa điểm nhiễu là những điểm đốm trắng đen khiến cho hình khó nhìn. Nếu để ý kĩ
hơn, chúng ta có thể thấy, các điểm nhiễu này có mức sáng chênh lệch rõ ràng so với những
điểm xung quanh điểm trắng nổi lên giữa khu vực màu đen. Để loại bỏ những điểm nhiễu này,
hay loại bỏ những điểm có mức sáng chênh lệch lớn bất thường, làm mờ ảnh là một trong những
phương pháp phổ biến nhất được áp dụng.
Cách để làm mờ những điểm có độ sáng bất thường trên ảnh. Biện pháp đơn giản nhất
chính là thay thế những điểm có độ sáng bất thường bằng trung bình độ sáng của những điểm
lân cận.
Với ý tưởng trên, chúng ta sẽ tính tích chập ảnh với ma trận nhân (kernel). Khi nhân tích

chập với ma trận này, giá trị đầu ra của điểm được tính sẽ bằng trung bình cộng của 8 điểm
xung quanh và giá trị của chính điểm đó.

a. Ví dụ minh họa:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('MyPictures/lenna_noi.png')
kernel = np.ones((3,3), np.float32)/9
blur_img = cv2.filter2D(img, -1, kernel)
f, axs = plt.subplots(1,2, figsize=(10,5))
axs[0].imshow(img)
axs[1].imshow(blur_img)
plt.show()

b. Giải thích
Đầu tiên, chương trình sẽ load hình ảnh vào bằng câu lệnh cv2.imread.
Câu lệnh kernel = np.ones((3,3), np.float32)/9 tạo ra một ma trận vng 3x3 với tất cả các
phần tử có giá trị là 1/9.
Hàm cv2.filter2D thực hiện việc nhân convolution giữa ảnh img và ma trận nhân kernel để
cho ra kết quả là ảnh đã làm mờ blur_img. Tham số -1 trong hàm cv2.filter2D để chỉ ảnh đầu ra
có cùng độ sâu màu ddepth với ảnh gốc.

16


1.3.5.

Lập trình ứng dụng các phép lọc ảnh


a. Lọc tuyến tính
• Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('MyPictures/opencv-logo.png')
kernel = np.ones((5,5),np.float32)/25
dst = cv2.filter2D(img,-1,kernel)
plt.subplot(121), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(dst), plt.title('Averaging')
plt.xticks([]), plt.yticks([])

plt.show()

• Bài tập mở rộng: thực hiện bài tập có các hàm sử dụng như gợi ý
dst=cv.blur(src, ksize[, dst[, anchor[, borderType]]])
dst=cv.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])
dst=cv.medianBlur(src, ksize[, dst])
dst=cv.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])

b. Biến đổi Fourier
• Các hàm sử dụng


Biế n đổi Fourier trong Numpy
+ FFT
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)


+ DFT
f_ishift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f_ishift)



Fourier Transform in OpenCV
17


dft = cv.dft(np.float32(img),flags = cv.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)
magnitude_spectrum = 20*np.log(cv.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))

# apply mask and inverse DFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv.idft(f_ishift)
img_back = cv.magnitude(img_back[:,:,0],img_back[:,:,1])



Performance Optimization of DFT
retval=cv.getOptimalDFTSize(vecsize)

• Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('MyPictures/messi5.jpg', 0)

f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20 * np.log(np.abs(fshift))
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(magnitude_spectrum, cmap='gray')
plt.title('Magnitude Spectrum FFT'), plt.xticks([]), plt.yticks([])
plt.show()

• Bài tập mở rộng: biến đổi DFT
+ Sử dụng các hàm tương ứng trong OpenCV là cv2.dft () và cv2.idft ()
+ Sử dụng hàm cv2.cartToPolar () để trả về biên độ và pha

1.3.6.

Các phép nổi biên

a. Hàm sử dụng
dst=cv.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])
dst=cv.Scharr(src, ddepth, dx, dy[, dst[, scale[, delta[, borderType]]]])
dst=cv.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
edges=cv.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])
edges=cv.Canny(dx, dy, threshold1, threshold2[, edges[, L2gradient]])

b. Lọc Laplace và Sobel làm nổi biên
+ Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('MyPictures/sudoku.jpg', 0)

laplacian = cv2.Laplacian(img, cv2.CV_64F)

18


sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
plt.subplot(2, 2, 1), plt.imshow(img, cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 2), plt.imshow(laplacian, cmap='gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 3), plt.imshow(sobelx, cmap='gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.subplot(2, 2, 4), plt.imshow(sobely, cmap='gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])
plt.show()

+ Bài tập mở rộng
+ Lọc sobel cho ảnh có kiểu dữ liệu là 8U và 64F
+ Làm nổi biên dùng lọc canny, sử dụng hàm: cv.Canny()

c. Biến đổi ảnh Pyramids
− Hàm sử dụng
dst=cv.pyrUp(src[, dst[, dstsize[, borderType]]])
dst=cv.pyrDown(src[, dst[, dstsize[, borderType]]])

+ Gaussian Pyramid

# generate Gaussian pyramid for A
G = A.copy()

gpA = [G]
for i in range(6):
G = cv.pyrDown(G)
gpA.append(G)

+ Laplacian Pyramids

# generate Laplacian Pyramid for A
lpA = [gpA[5]]
for i in range(5,0,-1):
GE = cv.pyrUp(gpA[i])
L = cv.subtract(gpA[i-1],GE)
lpA.append(L)


Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
higher_reso = cv2.imread('MyPictures/messi5.jpg')
cv2.imshow('higher_reso', higher_reso)
lower_reso = cv2.pyrDown(higher_reso)
cv2.imshow('lower_reso', lower_reso)
higher_reso2 = cv2.pyrUp(lower_reso)
cv2.imshow('higher_reso2', higher_reso2)
cv2.waitKey(0)
cv2.destroyAllWindows()

− Bài tập mở rộng
19



+ Thay đổi để sử dụng hàm cv2.pyrUp và cv2.pyrDown như gợi ý
src = cv2.pyrUp(src, dstsize=(2 *cols, 2*rows))
rc = cv2.pyrDown(src, dstsize=(cols//2, rows//2))

1.3.7.

Các phép biến đổi hình thái học

• Hàm sử dụng
dst=cv.dilate(scr, kernel[, dst[, anchor[, interations[, borderType[, borderValue]]]]])
dst=cv.erode(scr, kernel[, dst[, anchor[, interations[, borderType[, borderValue]]]]])
dst=cv.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

+ Opening
opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)

+ Closing
closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)

+ Morphological Gradient
gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)

+ Top Hat
tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)

+ Black Hat
blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)

• Kéo giãn ảnh (dilate)

+ Code mẫu: Sinh viên chạy các code này và tìm hiểu từng câu lệnh
import cv2
import numpy as np
img = cv2.imread('MyPictures/j.png', 0)
cv2.imshow('j.png', img)
print(img.shape)
kernel = np.ones((5, 5), np.uint8)
dilation = cv2.dilate(img, kernel, iterations=1)
cv2.imshow('dilation', dilation)
cv2.moveWindow('dilation', x=img.shape[1], y=0)
cv2.waitKey(0)
cv2.destroyAllWindows()

+ Bài tập mở rộng
Thay đổi lệnh cv2.dilate() thành các lệnh
erosion = cv2.erode(img, kernel, iterations=1)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)

20


→ Nhận xét kết quả khi thêm và thay các lệnh và các hàm trên

1.4. Bài tập áp dụng
a. Bài hiển thị ảnh bằng lệnh imshow
Viết đoạn code hiển thị các ảnh của sinh viên trong nhóm, ứng dụng các lệnh đã học ở

trên (cv2.IMREAD_GRAYSCALE, cv2.IMREAD_COLOR, cv2.IMREAD_UNCHANGED)
để hiển thị ảnh xám, màu, anpha và in ra (phiên bản của opencv dang sử dụng và tỉ lệ row/col;
colum/with; aisle)

b. Bài tập hiển thị ảnh bằng lệnh plt
Viết chương trình áp dụng hàm plt hiển thị ảnh theo ngưỡng nhị phân và ngưỡng thích
nghi
− Kết quả 1: Hiển thị ảnh gốc, BINARY, BINARY_INV, TRUNC, TOZERO,
TOZERO_INV.
− Kết quả 2: Hiển thị ảnh gốc, Global Thresholding (v=127), Adaptive Mean
Thresholding, Adaptive Gaussian Thresholding

c. Viết các chương trình hiển thị camera
− Viết chương trình mở camera và hiển thị kết hình ảnh camera theo hàm plt
− Viết chương trình mở camera và hiển thị kết hình ảnh camera theo hàm imshow, và
in ra kết quả frame.shape ra màn hình python
− Viết chương trình kiểm tra 2 camera có đang kết nối vào máy tính, nếu có camera nào
được kết nối thì kích hoạt nó sáng đèn lên một lần
− Viết chương trình phát video bằng cách đọc frame, kết quả hiển thị video theo frame
và in kết quả ra màn hình python theo FRAME_NOW

d. Viết các chương trình ứng dụng vẽ hình
− Viết chương trình tạo 3 thanh trackbar chọn màu R,G,B để vẽ hình trịn và hình chữ
nhật. (vẽ đường trịn có 2 cách: nhấn giữ chuột trái để vẽ khi kết thúc bằng một chấm
đỏ, hoặc giữ chuột trái kéo từ trong ra ngoài) bấm phím m để thay đổi hình vẽ (vẽ hình
chữ nhật bằng cách ấn chuột trái và rê chuột)
− Viết chương trình như yêu cầu trên nhưng thay đổi đường trịn thành hình trịn
21



×