BƯỚC 01
Bắt đầu từ đâu?
Học sau bài kích thước và kiểu dữ liệu. Cần hiểu chỉ số hàng, cột và lát cắt Python.
Bạn sẽ cắt một vùng ảnh, chọn điểm ảnh bằng mặt nạ và tạo bản sao. Ví dụ giúp bạn tránh sửa nhầm ảnh gốc khi chỉ muốn đổi một vùng nhỏ.
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install numpy matplotlibÝ nghĩa đoạn mã
Tạo môi trường riêng rồi gọi đúng Python trong môi trường. Không cần kích hoạt bằng một lệnh khác.
BƯỚC 02
Lát cắt cơ bản thường chia sẻ dữ liệu
Ta tạo ảnh xám có một khung sáng. Lấy một vùng bằng lát cắt cơ bản trả về view, nghĩa là vùng mới có thể trỏ vào cùng dữ liệu với ảnh gốc. Thay đổi view sẽ thay đổi nguồn.
Trong xử lý ảnh, lỗi này hay xảy ra khi tạo nhiều bản tăng cường dữ liệu từ cùng một mẫu. Hãy dùng np.shares_memory để kiểm tra thay vì chỉ so sánh tên biến.
from pathlib import Path
import json
import numpy as np
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
OUTPUT = Path(__file__).resolve().parent / "results"
OUTPUT.mkdir(exist_ok=True)
plt.rcParams.update({"font.size": 12, "axes.spines.top": False,
"axes.spines.right": False, "figure.facecolor": "#f3f7f6",
"axes.facecolor": "white", "axes.titleweight": "bold"})
FIGURE = OUTPUT / "numpy-slicing-copy.png"
original = np.zeros((64, 96), dtype=np.uint8)
original[8:56, 12:84] = 100
before = original.copy()
roi = original[20:44, 32:64]
assert np.shares_memory(original, roi)
roi[:] = 220
assert original[25, 40] == 220
print("View changes source:", not np.array_equal(before, original))Ý nghĩa đoạn mã
roi[:] ghi vào toàn bộ view. Bản before được tạo bằng copy nên vẫn giữ ảnh trước khi sửa. Chỉ gán tên biến khác không tạo dữ liệu độc lập.
Phân biệt đổi tham chiếu biến với sửa nội dung mảng.
BƯỚC 03
Copy khi cần giữ nguồn, mặt nạ khi cần chọn điều kiện
copy tạo vùng dữ liệu riêng. Boolean indexing chọn các phần tử thỏa điều kiện và thường trả về bản sao khi đọc. Tuy vậy, phép gán trực tiếp original[mặt nạ] = value vẫn sửa ảnh gốc. Hai thao tác này không có cùng tác dụng.
Ta giữ bản sao để phục vụ so sánh, rồi tạo mặt nạ từ ngưỡng. Mặt nạ có kích thước của ảnh xám và kiểu dữ liệu bool, không phải một ảnh màu ba kênh.
independent = original[20:44, 32:64].copy()
independent[:] = 10
assert not np.shares_memory(original, independent)
assert original[25, 40] == 220
mask = original > 150
selected = original[mask]
selected[:] = 0
assert original[mask].min() == 220
masked = np.where(mask, original, 0)
assert mask.dtype == bool and mask.shape == original.shape
print("Selected pixels:", int(mask.sum()))Ý nghĩa đoạn mã
np.where giữ nguyên kích thước, còn original[mặt nạ] trả về vector các pixel được chọn. Khi đưa mặt nạ vào công thức, cần phân biệt số pixel được chọn với kích thước không gian.
Đọc bằng boolean indexing và gán qua boolean indexing là hai trường hợp khác nhau.
BƯỚC 04
Vẽ nguồn trước và sau thao tác
Dùng cùng vmin và vmax để ba ảnh có thể so sánh. Nếu mỗi ảnh tự chọn miền màu, vùng có giá trị 100 và 220 có thể cùng hiện trắng, làm mất ý nghĩa của thí nghiệm.
Ảnh cuối giữ vùng có giá trị lớn hơn 150 và đưa phần còn lại về 0. Từ đây có thể nối sang bài broadcasting và chuẩn hóa mà không làm thay đổi dữ liệu gốc ngoài ý muốn.
fig, axes = plt.subplots(1, 3, figsize=(12, 8), layout="constrained")
for ax, data, title in zip(axes, [before, original, masked], ["Before slicing", "After editing view", "Boolean selection"]):
ax.imshow(data, cmap="gray", vmin=0, vmax=255)
ax.set_title(title)
ax.axis("off")
fig.savefig(FIGURE, dpi=100)
plt.close(fig)
print("Saved:", FIGURE.name)Ý nghĩa đoạn mã
Thang màu 0–255 cố định làm thay đổi cường độ có ý nghĩa giữa các ô. Hình ảnh chỉ bổ sung cho các assert về bộ nhớ và giá trị.
Bảo vệ ảnh gốc bằng copy tại nơi thực sự cần biến đổi độc lập.
BƯỚC 05
Chạy thử và đọc kết quả
View phải làm đổi nguồn, copy không làm đổi nguồn. Mặt nạ chọn đúng 768 pixel và ảnh thứ ba chỉ còn vùng chữ nhật sáng.

.\.venv\Scripts\python.exe numpy_slicing_copy.pyÝ nghĩa đoạn mã
Lệnh chạy toàn bộ tệp vừa tải. Nếu một assert không đúng, dừng lại và kiểm tra dữ liệu cùng bước tương ứng trước khi diễn giải hình.
Kiểm tra số liệu in ra trước, sau đó mới dùng hình để giải thích.
ĐẾN LƯỢT BẠN
Thử một thay đổi nhỏ
- Thay selected[:] = 0 bằng original[mặt nạ] = 0 rồi dự đoán assert nào không còn đúng.
- Sau đó sửa chương trình để giữ cả ảnh gốc và ảnh đã xóa vùng sáng.




