Python

3 cách lưu trữ và truy cập nhiều hình ảnh trong Python - Phần 1

Tại sao bạn muốn biết thêm về cac cách lưu trữ và truy cập hình ảnh khác nhau trong Python ? Nếu bạn phân chia một số hình ảnh 
theo màu sắc hoặc phát hiện từng khuôn mặt một bằng cách sử dụng OpenCV, thì bạn không cần phải lo lắng về điều đó. Ngay cả khi bạn sử dụng Thư viện hình ảnh Python(PIL) để vẽ đến vài trăm bức ảnh, bạn vẫn không cần. Lưu trữ hình ảnh trên đĩa, dưới dạng tệp như .png hoặc .jpg đều tiện lợi và phù hợp. 

Tuy nhiến số lượng hình ảnh cần thiết cho một nhiệm vụ nhất định ngày càng lớn hơn. Các thuật toán như mạng "convolutional neural" còn được gọi là convnets hoặc CNN, có thể xử lý các bộ dữ liệu lớn của hình ảnh và cải tiến thêm từ chúng. Nếu bạn quan tâm, bạn có thể đọc thêm về cách convnets có thể được sử dụng để xếp hạng ảnh tự chụp hoặc phân tích trạng thái tình cảm.

ImageNet là một cơ sở dữ liệu hình ảnh công cộng nổi tiếng được tập hợp để đào tạo các mô hình về các nhiệm vụ như phân loại, phát hiện và phân đoạn đối tượng và nó bao gồm hơn 14 triệu hình ảnh. 

Hãy suy nghĩ về việc mất bao lâu để tải tất cả chúng vào bộ nhớ để đào tạo, theo đợt, có thể hàng trăm hoặc hàng nghìn lần. 

Trong các hướng dẫn dưới đây bạn sẽ học về : 

  • Lưu trữ hình ảnh trên đĩa dưới dạng tệp .png
  • Lưu  trữ hình ảnh trong cơ sở dữ liệu ánh xạ bộ nhớ sét (LMDB)
  • Lưu trữ hình ảnh ở định dạng dữ liệu phân cấp (HDF5).

Một số vấn đề khám phá tiếp theo : 

  •  Tại sao phương pháp lưu trữ thay thế là đáng xen xét 
  •  Sự khác biệt về hiệu xuất là gì khi bạn đọc và viết các ảnh đơn lẻ.
  •  Sự khác biệt về hiệu xuất là gì khi bạn đọc và viết nhiều hình ảnh.
  •  ba phương pháp so sánh về cách sử dụng đĩa

Nếu không có phương pháp lưu trữ nào hiện tại, đừng lo lắng : 
Đối với bài viết này, tất cả những gì bạn cần là một nền tảng vững chắc trong Python và hiểu biết cơ bản về hình ảnh( rằng chúng thực sự bao gồm các mảng số đa chiều ) và bộ nhớ tương đối, chẳng hạn như chênh lệch giữa 10MB và 10GB.

Set Up 

Bạn sẽ cần một bộ dữ liệu hình ảnh để thử nghiệm, cũng như một vài Python packages.

A Dataset to Play With


Chúng tôi sẽ sử dụng bộ dữ liệu hình ảnh của Viện nghiên cứu nâng cao Canada (Canadian Institute for Advanced Research), được biết với với cái tên CIFAR-10, bao gồm 60.000 hình ảnh màu 32*32 pixel thuộc các lớp khác nhau, như chó, mèo và máy bay. Một cách tương đối, CIFAR không phải là một tập dữ liệu quá lớn, nhưng nếu chúng ta sử dụng một dữ liệu Tinylmages đầy đủ, thì bạn sẽ cần khoảng 400GB dung lượng đĩa trống, đây có thể là một yếu tố hạn chế.

Tín dụng cho bộ nhớ dữ liệu như được mô tả trong chương 3 của báo công nghệ này được gửi tới Alex Krizhevsky, Vinod Nải và Geoffrey Hinton.

Nếu bạn muốn theo dõi cùng các ví dụ code trong bài viết này, bạn có thể tải xuống CIFAR-10, chọn phiên bản PYthon. Bạn sẽ hy sinh 163MB dung lượng.

Khi bạn tải xuống và giải nén thư mục, bạn sẽ phát hiện ra rằng các tệp không phải là tệp hình ảnh có thể đọc được. Chúng thực sự đã được tuần tự hóa và lưu thành từng đợt bằng cPickle. 

Mặc dù chúng tôi không xem xét Pickle hoặc cPickle trong bài viết, ngoài việc trích xuất bộ dữ liệu CIFAR, điều đáng nói là mô-đun pickle Python có lợi thế chính là có thể tuần tự hóa bất kỳ đối tượng Python nào mà không cần thêm code hoặc chuyển đổi phần của bạn. Nó cũng có một nhược điểm nghiêm trọng tiềm ẩn là gây rủi ro bảo mật và không đối phó tốt khi xử lý một dữ liệu rất lớn.

Theo dõi đoạn code sau giải nén từng tệp trong 5 batch file và tải tất cả các hình ảnh vào một mảng NumPy:

import numpy as np
import pickle
from pathlib import Path

# Path to the unzipped CIFAR data
data_dir = Path("data/cifar-10-batches-py/")

# Unpickle function provided by the CIFAR hosts
def unpickle(file):
    with open(file, "rb") as fo:
        dict = pickle.load(fo, encoding="bytes")
    return dict

images, labels = [], []
for batch in data_dir.glob("data_batch_*"):
    batch_data = unpickle(batch)
    for i, flat_im in enumerate(batch_data[b"data"]):
        im_channels = []
        # Each image is flattened, with channels in order of R, G, B
        for j in range(3):
            im_channels.append(
                flat_im[j * 1024 : (j + 1) * 1024].reshape((32, 32))
            )
        # Reconstruct the original image
        images.append(np.dstack((im_channels)))
        # Save the label
        labels.append(batch_data[b"labels"][i])

print("Loaded CIFAR-10 training set:")
print(f" - np.shape(images)     {np.shape(images)}")
print(f" - np.shape(labels)     {np.shape(labels)}")

Tất cả các hình ảnh hiện có trong Ram trong biến hình ảnh, với dữ liệu meta tương ứng của chúng trong nhãn và sẵn sàng để bạn thao tác. Tiếp theo các bạn cài đặt gói Python mà bạn sẽ sử dụng cho ba phương thức.

Note : Khối code cuối cùng được sử dụng chuỗi f. bạn có thể đọc thêm trong Python 3 F-String : Cú pháp định dạng chuỗi cải tiến.

Thiết lập để lưu trữ hình ảnh trên đĩa


Bạn sẽ cần thiết lập môi trường của bạn cho phương thức lưu và truy cập những hình ảnh này từ đĩa mặc định. Bài viết này quy định bạn đã  cài python 3.x trên hệ thống của mình và sẽ sử dụng Pillow cho các thao tác hình ảnh :

$ pip install Pillow

Ngoài ra, nếu bạn thích, bạn có thể cài đặt nó bằng Anaconda :

$ conda install -c conda-forge pillow

Note : PIL là phiên bản gốc của thư viện hình ảnh Python, không còn được duy trì và không tương thích với Python 3.x. Nếu bạn đã cài 
đặt PIL trước đó, hãy đảm bảo gỡ cài đặt trước khi cài đặt Pillow, vì chúng có thể tồn tại cùng nhau.  

Bây giờ bạn đã sẵn sàng để lưu trữ và đọc hình ảnh từ đĩa.

Bắt đầu với LMDB

LMDB, đôi khi được goi là Cơ sở dữ liệu Lighting,... viết tắt của cơ sở dữ liệu Lightning Memory - mapped vì nó nhanh và sử dụng các tệp ánh xạ bộ nhớ. Nó có một kho lưu trữ khóa - giá trị, không phải cơ sở dữ liệu quan hệ. 

Về mặt triển khai, LMDB là một cây B +, cơ bản có nghĩa là nó là một cấu trúc đồ thị giống như cây được lưu trữ trong bộ nhớ trong đó mỗi phần tử giá trị khóa là một nút và các nút có thể có nhiều con. Các nút trên cùng cấp được liên kết với nhau để truyền tải nhanh. 

Quan trọng, các thành phần chính của cây B + được đặt tương ứng với kích thước trang của hệ điều hành máy chủ, tối đa hóa hiệu quả khi truy cập vào bất kỳ cặp giá trị khóa nào trong cơ sở dữ liệu. Do LMDB hiệu năng cao phụ thuộc rất nhiều vào điểm đặc biệt này, hiệu quả LMDB đã được chứng minh là phụ thuộc vào hệ thống tệp cơ bản và việc triển khai.

Một lý do quan trọng khác cho hiệu quả của LMDB là nó được ánh xạ bộ nhớ. Điều này có nghĩa là nó trả về con trỏ trực tiếp đến địa chỉ bộ nhớ của cả khóa và giá trị, mà không cần sao chép bất cứ thứ gì trong bộ nhớ như hầu hết các cơ sở dữ liệu khác. 

Những ai muốn tìm hiểu thêm một chút về các chi tiết triển khai bên trong của cây B + có thể xem bài viết này về cây B + và sau đó chơi với trực quan hóa việc chèn nút này. 

Nếu cây B + don don làm bạn quan tâm, đừng lo lắng. Bạn không cần phải biết nhiều về triển khai nội bộ của họ để sử dụng LMDB. Chúng tôi sẽ sử dụng liên kết Python cho thư viện LMDB C, có thể được cài đặt qua pip:

$ pip install lmdb

Bạn cũng có thể tùy chọn cài đặt qua Anaconda : 

$ conda install -c conda-forge python-lmdb

Kiểm tra xem bạn có thể "import" lmdb từ Python Shell không ?


Bắt đầu với HDF5

HDF5 là viết tắt của Định dạng dữ liệu phân cấp, định dạng tệp được gọi là HDF4 hoặc HDF5. Chúng tôi không cần phải lo lắng về HDF4, vì HDF5 là phiên bản được duy trì hiện tại. 

Thật thú vị, HDF có nguồn gốc từ Trung tâm Ứng dụng siêu máy tính quốc gia, dưới dạng định dạng dữ liệu khoa học nhỏ gọn, di động. Nếu bạn đang tự hỏi liệu nó có được sử dụng rộng rãi hay không, hãy xem NASA Giới thiệu về HDF5 từ dự án Dữ liệu Trái đất của họ. Các tệp 

HDF bao gồm hai loại đối tượng: 

  • Datasets 
  • Groups 

Datasets là các mảng đa chiều và các nhóm bao gồm các bộ dữ liệu hoặc các nhóm khác. Các mảng đa chiều có kích thước và loại bất kỳ có thể được lưu trữ dưới dạng tập dữ liệu, nhưng kích thước và loại phải được thống nhất trong một tập dữ liệu. Mỗi tập dữ liệu phải chứa một mảng N chiều đồng nhất. Điều đó nói rằng, bởi vì các nhóm và bộ dữ liệu có thể được lồng nhau, bạn vẫn có thể có được sự không đồng nhất mà bạn có thể cần:

$ pip install h5py

Cũng như các thư viện khác, bạn có thể luân phiên cài đặt qua Anaconda : 

$ conda install -c conda-forge python-lmdb

Nếu bạn có thể nhập "h5py" từ Python Shell, mọi thứ sẽ được thiết lập đúng. 

 

 

Registration Login
Sign in with social account
or
Lost your Password?
Registration Login
Sign in with social account
or
A password will be send on your post
Registration Login
Registration