Tạo các phép tích chập và thực hiện gộp nhóm

1. Trước khi bắt đầu

Trong lớp học lập trình này, bạn sẽ tìm hiểu về các phép tích chập và lý do khiến chúng có sức mạnh lớn trong các trường hợp thị giác máy tính.

Trong lớp học lập trình trước, bạn đã tạo một Mạng nơ-ron sâu (DNN) đơn giản để thị giác máy tính nhận dạng các mặt hàng thời trang. Điều này bị hạn chế vì yêu cầu mặt hàng quần áo phải là thứ duy nhất trong bức ảnh và phải được đặt ở giữa.

Tất nhiên, đây không phải là một tình huống thực tế. Bạn sẽ muốn DNN có thể xác định mặt hàng quần áo trong ảnh có các vật thể khác hoặc khi mặt hàng đó không nằm ở vị trí chính giữa. Để làm được việc này, bạn cần sử dụng các phép tích chập.

Điều kiện tiên quyết

Lớp học lập trình này dựa trên những nội dung đã hoàn thành trong 2 phần trước, Chào mừng đến với "Hello, World" của học máyXây dựng mô hình thị giác máy tính. Vui lòng hoàn tất các lớp học lập trình đó trước khi tiếp tục.

Kiến thức bạn sẽ học được

  • Tích chập là gì
  • Cách tạo bản đồ đối tượng
  • Gộp là gì

Sản phẩm bạn sẽ tạo ra

  • Bản đồ đối tượng của một hình ảnh

Bạn cần có

Bạn có thể tìm thấy đoạn mã cho phần còn lại của lớp học lập trình chạy trong Colab.

Bạn cũng cần cài đặt TensorFlow và các thư viện mà bạn đã cài đặt trong lớp học lập trình trước.

2. Tích chập là gì?

Tích chập là một bộ lọc truyền qua hình ảnh, xử lý hình ảnh đó và trích xuất các đặc điểm quan trọng.

Giả sử bạn có hình ảnh một người đang đi giày thể thao. Làm cách nào để bạn phát hiện thấy một chiếc giày thể thao xuất hiện trong hình ảnh? Để chương trình của bạn "nhận diện" hình ảnh là một chiếc giày thể thao, bạn sẽ phải trích xuất các đặc điểm quan trọng và làm mờ các đặc điểm không cần thiết. Đây được gọi là ánh xạ tính năng.

Về lý thuyết, quy trình liên kết tính năng rất đơn giản. Bạn sẽ quét từng pixel trong hình ảnh rồi xem xét các pixel lân cận. Bạn nhân các giá trị của những pixel đó với trọng số tương đương trong một bộ lọc.

Ví dụ:

Tích chập trên hình ảnh

Trong trường hợp này, ma trận tích chập 3x3 hoặc nhân hình ảnh được chỉ định.

Giá trị pixel hiện tại là 192. Bạn có thể tính giá trị của pixel mới bằng cách xem xét các giá trị lân cận, nhân các giá trị đó với các giá trị được chỉ định trong bộ lọc và đặt giá trị pixel mới làm số tiền cuối cùng.

Giờ là lúc bạn khám phá cách hoạt động của các phép tích chập bằng cách tạo một phép tích chập cơ bản trên hình ảnh thang độ xám 2D.

Bạn sẽ minh hoạ điều đó bằng hình ảnh ascent từ SciPy. Đây là một bức ảnh tích hợp đẹp mắt với nhiều góc và đường nét.

3. Bắt đầu lập trình

Bắt đầu bằng cách nhập một số thư viện Python và hình ảnh về đường bay lên:

import cv2
import numpy as np
from scipy import misc
i = misc.ascent()

Tiếp theo, hãy dùng thư viện Pyplot matplotlib để vẽ hình ảnh nhằm biết hình ảnh trông như thế nào:

import matplotlib.pyplot as plt
plt.grid(False)
plt.gray()
plt.axis('off')
plt.imshow(i)
plt.show()

edb460dd5397f7f4.png

Bạn có thể thấy đó là hình ảnh của một cầu thang. Bạn có thể thử và tách biệt nhiều tính năng. Ví dụ: có các đường thẳng đứng rõ ràng.

Hình ảnh được lưu trữ dưới dạng một mảng NumPy, vì vậy, chúng ta có thể tạo hình ảnh đã chuyển đổi bằng cách chỉ cần sao chép mảng đó. Các biến size_x và size_y sẽ lưu giữ kích thước của hình ảnh để bạn có thể lặp lại hình ảnh đó sau này.

i_transformed = np.copy(i)
size_x = i_transformed.shape[0]
size_y = i_transformed.shape[1]

4. Tạo ma trận tích chập

Trước tiên, hãy tạo một ma trận tích chập (hoặc hạt nhân) dưới dạng một mảng 3x3:

# This filter detects edges nicely
# It creates a filter that only passes through sharp edges and straight lines. 
# Experiment with different values for fun effects.
#filter = [ [0, 1, 0], [1, -4, 1], [0, 1, 0]] 
# A couple more filters to try for fun!
filter = [ [-1, -2, -1], [0, 0, 0], [1, 2, 1]]
#filter = [ [-1, 0, 1], [-2, 0, 2], [-1, 0, 1]]
 # If all the digits in the filter don't add up to 0 or 1, you 
# should probably do a weight to get it to do so
# so, for example, if your weights are 1,1,1 1,2,1 1,1,1
# They add up to 10, so you would set a weight of .1 if you want to normalize them
weight  = 1

Bây giờ, hãy tính số pixel đầu ra. Lặp lại trên hình ảnh, chừa ra một lề 1 pixel và nhân mỗi vùng lân cận của pixel hiện tại với giá trị được xác định trong bộ lọc.

Điều đó có nghĩa là điểm ảnh lân cận hiện tại ở phía trên và bên trái điểm ảnh đó sẽ được nhân với mục trên cùng bên trái trong bộ lọc. Sau đó, nhân kết quả với trọng số và đảm bảo rằng kết quả nằm trong phạm vi từ 0 đến 255.

Cuối cùng, hãy tải giá trị mới vào hình ảnh đã chuyển đổi:

for x in range(1,size_x-1):
  for y in range(1,size_y-1):
      output_pixel = 0.0
      output_pixel = output_pixel + (i[x - 1, y-1] * filter[0][0])
      output_pixel = output_pixel + (i[x, y-1] * filter[0][1])
      output_pixel = output_pixel + (i[x + 1, y-1] * filter[0][2])
      output_pixel = output_pixel + (i[x-1, y] * filter[1][0])
      output_pixel = output_pixel + (i[x, y] * filter[1][1])
      output_pixel = output_pixel + (i[x+1, y] * filter[1][2])
      output_pixel = output_pixel + (i[x-1, y+1] * filter[2][0])
      output_pixel = output_pixel + (i[x, y+1] * filter[2][1])
      output_pixel = output_pixel + (i[x+1, y+1] * filter[2][2])
      output_pixel = output_pixel * weight
      if(output_pixel<0):
        output_pixel=0
      if(output_pixel>255):
        output_pixel=255
      i_transformed[x, y] = output_pixel

5. Kiểm tra kết quả

Bây giờ, hãy vẽ biểu đồ cho hình ảnh để xem hiệu ứng của việc truyền bộ lọc lên hình ảnh:

# Plot the image. Note the size of the axes -- they are 512 by 512
plt.gray()
plt.grid(False)
plt.imshow(i_transformed)
#plt.axis('off')
plt.show()   

48ff667b2df812ad.png

Hãy xem xét các giá trị bộ lọc sau đây và tác động của chúng đối với hình ảnh.

Sử dụng [-1,0,1,-2,0,2,-1,0,1] sẽ cho bạn một tập hợp các đường thẳng dọc rất rõ ràng:

Bộ lọc phát hiện đường thẳng đứng

Sử dụng [-1,-2,-1,0,0,0,1,2,1] sẽ cho bạn các đường ngang:

Phát hiện đường kẻ ngang

Khám phá các giá trị khác nhau! Ngoài ra, hãy thử các bộ lọc có kích thước khác nhau, chẳng hạn như 5x5 hoặc 7x7.

6. Tìm hiểu về tính năng gộp

Sau khi xác định được các đặc điểm thiết yếu của hình ảnh, bạn sẽ làm gì? Bạn sử dụng bản đồ đối tượng kết quả như thế nào để phân loại hình ảnh?

Tương tự như các phép tích chập, phân nhóm giúp ích rất nhiều trong việc phát hiện các đặc điểm. Các lớp gộp giúp giảm tổng lượng thông tin trong hình ảnh nhưng vẫn duy trì những đặc điểm được phát hiện là có trong hình ảnh.

Có một số loại gộp nhóm, nhưng bạn sẽ sử dụng một loại gọi là Gộp nhóm tối đa (Max).

Lặp lại trên hình ảnh và tại mỗi điểm, hãy xem xét pixel và các pixel lân cận ngay bên phải, bên dưới và bên phải bên dưới. Lấy hình ảnh lớn nhất trong số đó (do đó có tính năng max pooling) và tải hình ảnh đó vào hình ảnh mới. Do đó, hình ảnh mới sẽ có kích thước bằng 1/4 kích thước của hình ảnh cũ. Gộp tối đa

7. Viết mã cho việc gộp

Đoạn mã sau đây sẽ cho thấy một nhóm (2, 2). Chạy chương trình để xem kết quả.

Bạn sẽ thấy rằng mặc dù hình ảnh chỉ bằng 1/4 kích thước của hình ảnh gốc, nhưng vẫn giữ được tất cả các đặc điểm.

new_x = int(size_x/2)
new_y = int(size_y/2)
newImage = np.zeros((new_x, new_y))
for x in range(0, size_x, 2):
  for y in range(0, size_y, 2):
    pixels = []
    pixels.append(i_transformed[x, y])
    pixels.append(i_transformed[x+1, y])
    pixels.append(i_transformed[x, y+1])
    pixels.append(i_transformed[x+1, y+1])
    pixels.sort(reverse=True)
    newImage[int(x/2),int(y/2)] = pixels[0]
 
# Plot the image. Note the size of the axes -- now 256 pixels instead of 512
plt.gray()
plt.grid(False)
plt.imshow(newImage)
#plt.axis('off')
plt.show()

1f5ebdafd1db2595.png

Lưu ý các trục của biểu đồ đó. Giờ đây, hình ảnh có kích thước 256x256, bằng 1/4 kích thước ban đầu và các đối tượng được phát hiện đã được cải thiện mặc dù hiện có ít dữ liệu hơn trong hình ảnh.

8. Xin chúc mừng

Bạn đã xây dựng mô hình thị giác máy tính đầu tiên! Để tìm hiểu cách cải thiện thêm các mô hình thị giác máy tính, hãy chuyển sang phần Xây dựng mạng nơ-ron tích chập (CNN) để cải thiện thị giác máy tính.