Bạn đã bao giờ mơ ước xây dựng Ứng dụng Xác định Hình ảnh Tương tự của riêng mình nhưng lại lo sợ thiếu kiến thức về Deep learning, Convolutional Neural Network và hơn thế nữa? Đừng lo lắng. Hướng dẫn sau đây sẽ giúp bạn bắt đầu và giúp bạn viết mã Ứng dụng Xác định Hình ảnh Tương tự của riêng mình bằng toán học cơ bản.
Trước khi chúng ta chuyển sang toán học và mã, tôi sẽ hỏi bạn một câu hỏi đơn giản. Đưa ra hai hình ảnh tham chiếu và một hình ảnh thử nghiệm, bạn nghĩ hình ảnh thử nghiệm tương tự hình ảnh nào:
* Tham chiếu 1

* Tham chiếu 2

* Thử nghiệm

Nếu bạn tin rằng Hình ảnh Thử nghiệm giống với hình ảnh tham chiếu đầu tiên thì bạn đã đúng. Nếu bạn tin điều ngược lại thì hãy cùng nhau tìm hiểu sức mạnh của toán học và lập trình.
Vector hình ảnh
Mọi hình ảnh được lưu trữ trong máy tính dưới dạng các con số và một vectơ của những con số đó có thể mô tả hoàn toàn hình ảnh được gọi là Vector Hình ảnh.
Khoảng cách Euclide
Khoảng cách Euclide thể hiện khoảng cách giữa hai điểm bất kỳ trong không gian n chiều. Vì ta biểu diễn hình ảnh của mình dưới dạng vector, chúng có thể được xem như một điểm trong không gian n chiều và ta có thể sử dụng khoảng cách euclide để tìm khoảng cách giữa chúng.

Histogram
Histogram là một trực quan hóa của các giá trị số. Ta sẽ sử dụng vector hình ảnh để biểu thị cho cả ba hình ảnh trên và sau đó tìm khoảng cách euclide giữa chúng. Dựa trên các giá trị trả về, hai hình ảnh có khoảng cách nhỏ hơn có nghĩa là tương tự nhau hơn.

Để xác định hai hình ảnh tương tự nhau, ta thực hiện theo cách tiếp cận sau:
- Đọc các tệp hình ảnh dưới dạng một mảng.
- Vì các tệp hình ảnh được tô màu nên có 3 kênh cho các giá trị RGB. Ta sẽ làm phẳng chúng sao cho mỗi hình ảnh là một mảng 1-D duy nhất.
- Khi ta có các tệp hình ảnh của mình dưới dạng một mảng, chúng ta sẽ tạo histogram cho mỗi hình ảnh, trong đó đối với mỗi chỉ mục 0 – 255, ta đếm sự xuất hiện của giá trị pixel đó trong hình ảnh.
- Dựa vào histogram, ta sử dụng Khoảng cách Euclid để tìm sự khác biệt của hai histogram.
- Dựa trên khoảng cách giữa các histogram của hình ảnh thử nghiệm và các hình ảnh tham chiếu, ta có thể xác định hai hình nào giống nhau hơn.
Coding
Import các thư viện cần thiết
from PIL import Image
from collections import Counter
import numpy as np
Ta sẽ sử dụng NumPy để lưu trữ hình ảnh dưới dạng mảng, PIL.Image để đọc hình ảnh dưới dạng giá trị số và collections.Counter để đếm số lần mỗi giá trị pixel (0-255) xuất hiện trong hình ảnh.
Đọc hình ảnh
img1 = Image.open('image1.jpg')
img1_arr = np.asarray(img1)
print(np.shape(img1_arr))
>>> (250, 320, 3)
Ta có thể thấy rằng hình ảnh ngoài đã được đọc thành công dưới dạng mảng 3-D. Trong bước tiếp theo, ta cần làm phẳng mảng 3-D này thành mảng 1 chiều.
img1_arr_1D = img1_arr.flatten()
print(np.shape(img1_arr_1D))
>>> (245760, )
Ta thực hiện các bước tương tự cho hai hình ảnh còn lại. Hãy thử tự thực hiện điều đó.
Tạo Count-Histogram-Vector
RH1 = Counter(img1_arr_1D)
Dòng mã trên trả về một dictionary trong đó khóa tương ứng với giá trị pixel và giá trị của khóa là số lần pixel đó xuất hiện trong hình ảnh.
Một hạn chế của khoảng cách Euclide là nó yêu cầu tất cả các vector phải được chuẩn hóa tức là cả hai vector cần phải có cùng kích thước. Để đảm bảo rằng vector histogram được chuẩn hóa, ta sẽ sử dụng vòng lặp for từ 0-255 và tạo histogram với giá trị của khóa nếu khóa xuất hiện trong hình ảnh, ngược lại ta thêm số 0.
H1 = []
for i in range(256):
if i in RH1.keys():
H1.append(RH1[i])
else:
H1.append(0)
Đoạn mã trên tạo ra một vector có kích thước (256,) trong đó mỗi chỉ mục tương ứng với giá trị pixel và giá trị tương ứng với số lượng pixel trong hình ảnh đó.
Thực hiện tương tự với 2 hình ảnh còn lại. Như vậy, ta có các vector cuối cùng cho cả hình ảnh tham chiếu và hình ảnh thử nghiệm. Việc cần làm tiếp theo là tính toán khoảng cách và dự đoán.
Hàm khoảng cách Euclide
def Euclide(H1,H2):
distance = 0
for i in range(len(H1)):
distance += np.square(H1[i]-H2[i])
return np.sqrt(distance)
Hàm trên nhận hai đối số là hai histogram và trả về khoảng cách euclide giữa chúng.
Đánh giá
Chúng ta đã có mọi thứ cần thiết để xác định sự tương đồng của các hình ảnh. Bây giờ, hãy áp dụng để tính khoảng cách giữa hình ảnh thử nghiệm và hình ảnh tham chiếu đầu tiên.
dist_test_img_1 = Euclide(H1,test_H)
print("Khoảng cách giữa Image_1 và Hình Test là: {}".format(dist_test_img_1))
>>> Khoảng cách giữa Image_1 và Hình Test là: 9882.175468994668
Với hình ảnh tham chiếu thứ 2
dist_test_img_2 = Euclide(H2,test_H)
print("Khoảng cách giữa Image_2 và Hình Test là: {}".format(dist_test_img_2))
>>> Khoảng cách giữa Image_2 và Hình Test là: 137929.0223122023
Kết luận
Dựa trên các kết quả trên, chúng ta có thể thấy rằng khoảng cách giữa hình ảnh thử nghiệm và hình ảnh tham chiếu đầu tiên nhỏ hơn nhiều so với khoảng cách giữa hình thử nghiệm và hình ảnh tham chiếu thứ hai. Điều này có ý nghĩa vì cả hình ảnh thử nghiệm và hình ảnh tham chiếu đầu tiên đều là chim bồ câu trong khi hình ảnh tham chiếu thứ hai là con công.