Tọa độ điểm ảnh python

Vẽ hình, các ký tự hay viết chử lên bức ảnh đó là những thao tác mà ở bài trước tôi đả hướng dẩn. Trong bài viết này, tôi sẽ giới thiệu một số điều cơ bản về các thao tác hình ảnh đơn giản mà chúng ta có thể thực hiện.

I. Giới thiệu.

Mỗi hình ảnh chia nhỏ thành các khung. Mỗi khung, giống như một hình ảnh nhỏ, sau đó chia thành các điểm ảnh được lưu trữ trong các hàng và cột trong khung hình / hình ảnh. Mỗi pixel có một vị trí tọa độ, và mỗi điểm ảnh bao gồm các giá trị màu. Chúng ta hãy nghiên cứu một số ví dụ về việc tiếp cận các điểm khác nhau của các nguyên tắc này.

II. Các thao tác về hình ảnh.

1. Hướng dẫn.

Chúng ta bắt đầu bằng cách đọc hình ảnh như thường lệ. Bạn có thể sử dụng hình ảnh của bạn .

import cv2
import numpy as np

img = cv2.imread['watch.jpg',cv2.IMREAD_COLOR]

Bây giờ, chúng ta có thể tham khảo các điểm ảnh cụ thể, như sau: Lấy điểm ảnh với tọa độ 55x55

px = img[55,55]

Tiếp theo, chúng ta thực sự có thể thay đổi một điểm ảnh: Thay đổi bằng cách gán cho nó với một điểm màu có mã RGB [255,255,255] Lúc này ta sẽ thấy có một điểm chấm nhỏ trên bức ảnh. Vì đây đang thục hiện với các điểm ảnh nên mình không đưa ra ví dụ minh họa , nó có kích thước quá nhỏ.

img[55,55] = [255,255,255]

Sau đó in điểm ảnh tham khảo:

px = img[55,55]
print[px]

Bây giờ nên khác. Tiếp theo, chúng ta có thể tham chiếu ROI [ Region of Image], như sau: Nghĩa là lấy vùng quan tâm có tọa độ

px = img[200:500,200:500]
print[px]

Chúng tôi cũng có thể sửa đổi ROI, như sau: Tô màu cho vùng quan tâm nhé.

img[100:150,100:150] = [255,255,255]

Chúng ta có thể tham khảo một số đặc điểm của hình ảnh:

Thuộc tính hình ảnh bao gồm số hàng, cột và kênh, loại dữ liệu hình ảnh, số pixel vv Hình dạng hình ảnh được truy cập bằng img.shape. Nó trả về một tuple của số hàng, cột và các kênh [nếu hình ảnh là màu]: Nếu hình ảnh màu xám, thì tuple trả lại chỉ chứa số hàng và cột. Vì vậy, nó là một phương pháp tốt để kiểm tra nếu tải hình ảnh là màu xám hoặc màu sắc hình ảnh.

print[img.shape]

Tổng số pixel được truy cập

print[img.size]

Loại dữ liệu hình ảnh thu được bằng

print[img.dtype]

Và chúng tôi có thể thực hiện các hoạt động, như: Đôi khi, bạn sẽ phải chơi với một vùng hình ảnh nhất định. Đối với việc dò tìm mắt trong hình ảnh, việc dò tìm khuôn mặt đầu tiên được thực hiện trên toàn bộ hình ảnh và khi có mặt, chúng ta sẽ chọn vùng mặt và tìm kiếm mắt bên trong thay vì tìm kiếm toàn bộ hình ảnh. Nó cải thiện độ chính xác [vì mắt luôn ở trên khuôn mặt] và hiệu suất [vì chúng ta tìm kiếm một khu vực nhỏ] ROI lại thu được bằng cách sử dụng lập chỉ mục Numpy. Ở đây tôi chọn mặt đồng hồ và sao chép nó vào một khu vực khác trong hình ảnh:

watch_face = img[100:200,200:300]
img[0:100,0:100] = watch_face

cv2.imshow['image',img]
cv2.waitKey[0]
cv2.destroyAllWindows[]

2. Kết quả.

Điều này sẽ làm việc với hình ảnh của tôi, nhưng có thể không cho hình ảnh của bạn, tùy thuộc vào kích thước. Đầu ra trong trường hợp của tôi:

Đây là một số hoạt động đơn giản. Trong hướng dẫn tiếp theo, chúng tôi sẽ giới thiệu một số thao tác hình ảnh nâng cao hơn mà chúng tôi có thể thực hiện.

III. Tài liệu tham khảo.

//docs.opencv.org/ //techmaster.vn/ //pythonprogramming.net/

Cấu trúc dữ liệu ảnh trong OpenCV

Cấu trúc dữ liệu hình ảnh trong OpenCV được tổ chức dưới dạng một ma trận [số học] 3 chiều. Thứ tự các chiều của ma trận được sắp xếp theo chiều cao, chiều rộng và kênh màu [tiếng Anh: height, width, channel]. Mỗi phần tử trong ma trận này có kiểu dữ liệu là số nguyên [0-255] hoặc số thực [0-1] mô tả giá trị của mức sáng [tiếng Anh: intensity].

Trong Xử Lý Ảnh, mức sáng của ảnh chạy trong miền giá trị 0-255. Màu đen "tuyệt đối" mang giá trị 0, màu trắng "tinh khôi" mang giá trị 255. Màu xám đậm sẽ có giá trị lệch về 0 nhiều, và màu xám nhạt lệch về phía 255. Do đó, đối với ảnh xám [hay còn gọi là ảnh "trắng đen", dĩ nhiên có màu xám tồn tại nha chớ hỏng phải nhị phân :D] ta chỉ cần một kênh màu để mô tả và lưu trữ.

Ảnh màu được biểu diễn bằng cách pha ba màu cơ bản là Đỏ [Red], Xanh Lá [Green] và Xanh Dương [Blue] - còn gọi là hệ màu RGB. Ở mỗi kênh màu đỏ hoặc xanh dương hoặc xanh lá được biểu diễn mức sáng trong miền giá trị 0-255. Một bộ giá trị 3 kênh RGB [trong lập trình gọi là tuple] biểu diễn một sắc màu. Như vậy, tổng cộng ta sẽ có tổ hợp của 255 x 255 x 255 = 16,581,375 - 16 triệu màu!~

Do đó, đối với ảnh màu ta cần 3 kênh màu để lưu trữ. Thứ tự kênh màu trong OpenCV được sắp theo BGR [Blue, Green, Red]. Lưu ý: màu đen được biểu diễn theo 3 kênh sẽ là [0, 0, 0], màu trắng là [255, 255, 255], và các mức xám sẽ được biểu diễn là [K, K, K] với giá trị K nằm trong đoạn [0, 255].

OpenCV [phiên bản Python] sử dụng cấu trúc dữ liệu Numpy, do đó ảnh đọc lên bằng câu lệnh cv2.imread[] sẽ trả ra một numpy.array [Numpy Array]. Các thao tác ta thực hiện sẽ xử lý trên Numpy Array! Do đó, ta vô tư sử dụng các hàm có trong thư viện Numpy lên ma trận ảnh.

Ví dụ: một ảnh màu có kích thước 60 x 60 thì ma trận có hình dạng như thế nào, và có bao nhiêu phần tử?

Đáp: kích thước ma trận sẽ là 60 x 60 x 3. Số phần tử trong ma trận bằng 60 x 60 x 3 = 10,800. Ảnh xám có kích thước 60 x 60 pixel thì ma trận biểu diễn sẽ có kích thước 60 x 60 [x 1].

Để "thấm thía" [hiểu rõ] hơn về cấu trúc dữ liệu của OpenCV, ta thử load hình sau lên và in ra thử:

simple.png

read_simple_image.py

import cv2
img = cv2.imread["simple.png"]
print[img]
print["Blue layer [%d]:" % img[:,:,0].size, img[:,:,0]]
print["Green layer [%d]:" % img[:,:,1].size, img[:,:,1]]
print["Red layer [%d]:" % img[:,:,2].size, img[:,:,2]]
print["Image shape:", img.shape] # [60, 60, 3]

Thực thi script python trên bạn sẽ thấy trên màn hình in ra bộ ba các mức sáng cấu thành nên màu của các ô vuông nhỏ trong hình simple.png.

  • img: cấu trúc dữ liệu Numpy
  • img.shape: in ra kích thước ma trận 60x60x3
  • img[:,:,0]: lấy ra một ma trận 2D ở kênh Blue, kích thước 60x60
  • img[:,:,0].size: số phần tử trong ma trận 60x60=3600

Các màu sắc của ô vuông trong ảnh ví dụ mình cố ý tạo theo các mã màu sau [BGR]:

simple_bgr.png

Ảnh gốc được Minh tạo ra bởi đoạn script sau:

create_simple_image.py

import cv2
import numpy as np

data = np.zeros[[60, 60, 3]]
h, w, c = data.shape

color_map = [
    [255, 0, 0], # blue
    [0, 255, 0], # green
    [0, 0, 255], # red
    [0, 0, 0], # black
    [255, 255, 255], # white
    [100, 100, 100], # grey
    [120, 50, 10],
    [36, 167, 227],
    [240, 212, 0],
]

assert h == w
step = h // 3
i = 0
for row in range[3]:
    for col in range[3]:
        data[row*step:[row+1]*step, col*step:[col+1]*step, :] = color_map[i]
        i += 1

cv2.imwrite["simple.png", data]
print["Done writing image: simple.png"]

Vòng lặp Minh sẽ lặp 9 lần [tương ứng 9 ô], mỗi ô có diện tích 20x20 và mình "fill" màu sắc với bộ ba mức sáng đọc từ danh sách "color_map" ra. Numpy cho phép ta đọc ra hoặc ghi vào một khối ma trận với các chỉ số trải dài liên tục. Cú pháp khác quen thuộc trong lập trình Python: data[Y_FROM:Y_TO, X_FROM:X_TO, C_FROM:C_TO].

Trục tọa độ ảnh. Pixel là gì?

  • Gốc tọa độ ảnh đặt ở góc phía trên bên trái.
  • Trục nằm dọc là trục y - tương ứng với chiều cao ảnh.
  • Trục nằm ngang là trục x - tương ứng với chiều rộng ảnh.
  • Trục z là trục chiều sâu [bạn tưởng tượng nó tương tự khối lập phương 3D đã từng học ở lớp 12 á] - tương ứng với kênh màu ảnh. Lưu ý: ảnh xám có thể KHÔNG CÓ trục z; hoặc có trục z nhưng một kênh; hoặc có trục z ba kênh nhưng màu sắc đều là xám => túm lại chỉ là các cách biểu diễn khác nhau của cùng một nội dung ảnh. Bạn tưởng tượng rằng kiểu như là: bạn đi siêu thị chọn một giỏ đựng hàng vừa đủ 4 món đồ bạn mua, HOẶC bạn chọn một giỏ đựng hàng to bự dư sức chứa cũng 4 món đồ bạn định mua đó => không có vấn đề gì cả nếu giỏ / sức chứa bạn to hơn nội dung bạn cần đựng trong nó :].
  • Một điểm trên ảnh ta gọi là một pixel. Pixel [tiếng Anh: picture element] là một điểm ảnh.

Ảnh minh họa tọa độ các điểm trong ảnh [ma trận 2D] có kích thước 7x11 [height x width]:

[nguồn ảnh: //math.hws.edu/graphicsbook/c2/s1.html]

Ví dụ 1: Giả sử biến img chứa dữ liệu của ma trận 7x11, ta muốn:

  • Lấy giá trị mức sáng ở tọa độ gốc => img[0, 0]
  • Lấy giá trị mức sáng tại [x=3, y=5] => img[5, 3] => BỞI VÌ OpenCV lưu theo H x W [x C]. Nếu ta dùng img[3, 5] là sai/nhầm nhé!
  • Lấy vùng ảnh y chạy từ 2->5 và x chạy từ 4->8 [tổng cộng 4*5=20 phần tử] => img[2:6, 4:9]

Ví dụ 2: Giả sử biến img chứa dữ liệu ảnh của một ảnh màu Full HD - độ phân giải ảnh 1080p [1920x1080 - width x height]. Như vậy thì:

  • Đọc bằng OpenCV, img có "shape" như sau: 1080 x 1920 x 3 => 6,220,800 [phần tử trong ma trận]
  • Cắt một vùng ảnh từ ảnh gốc => img[y_from:y_to, x_from:x_to, :]
  • Cắt một vùng ảnh từ ảnh gốc VÀ chỉ lấy kênh màu XANH DƯƠNG [B] => img[y_from:y_to, x_from:x_to, 0]
  • Cắt một vùng ảnh từ ảnh gốc VÀ chỉ lấy kênh màu XANH LÁ [G] => img[y_from:y_to, x_from:x_to, 1]
  • Cắt một vùng ảnh từ ảnh gốc VÀ chỉ lấy kênh màu ĐỎ [R] => img[y_from:y_to, x_from:x_to, 2]
  • Lấy giá trị mức sáng trên kênh màu xanh dương [Blue] tại tọa độ x=555, y=777 => img[777, 555, 0]

y_from, y_to, x_from, x_to là các giá trị số nguyên nằm trong kích thước ảnh gốc [không bị lòi ra ngoài hoặc số âm].

Gốc tọa độ của ảnh không giống với gốc tọa độ trong toán học. Do đó, biểu diễn vị trí tọa độ pixel trong ảnh sẽ theo gốc tọa độ ảnh. Ta phải nắm rõ cách tổ chức này để lấy đúng giá trị pixel / vùng trên ảnh. Bài này là kiến thức nền tảng vô cùng quan trọng để bạn tiếp tục tìm hiểu thư viện OpenCV cho Xử Lý Ảnh.

Bài viết tiếp theo Tut 1.2: Xử lý ảnh - Chuyển đổi ảnh OpenCV sang Pillow và ngược lại

Cảm ơn bạn đã theo dõi bài viết. Hãy kết nối với tớ nhé!

  • Minh: //www.facebook.com/minhng.info
  • Khám phá xử lý ảnh - GVGroup: //www.facebook.com/groups/ip.gvgroup

Khám phá xử lý ảnh - GVGroup

Danh sách bài viết series OpenCV:

  • Hashtag #OpenCV
  • Tut 1: Xử lý ảnh - OpenCV đọc ghi hình ảnh [code Python và C++]
  • Tut 1.1: Xử lý ảnh - Cấu trúc dữ liệu ảnh trong OpenCV. Pixel là gì?
  • Tut 1.2: Xử lý ảnh - Chuyển đổi ảnh OpenCV sang Pillow và ngược lại
  • Tut 2: Xử lý ảnh - OpenCV resize, crop và padding hình ảnh [code Python và C++]
  • Tut 3: Xử lý ảnh - OpenCV biến đổi mức sáng hình ảnh [code Python]
  • Tut 4: Xử lý ảnh - OpenCV vùng quan tâm [ROI] là gì? [code Python]
  • Tut 4.1: Xử lý ảnh - OpenCV: vẽ văn bản, đường thẳng, mũi tên, hình chữ nhật, hình tròn, ellipse, đa giác
  • Tut 4.2: Xử lý ảnh - Pha trộn ảnh trong OpenCV [blending]
  • Tut 5: Xử lý ảnh - OpenCV ảnh nhị phân
  • Tut 6: Xử lý ảnh - OpenCV cân bằng sáng [histogram equalization]
  • Tut 7: Xử lý ảnh - OpenCV kỹ thuật cửa sổ trượt [sliding window]
  • Tut 8: Xử lý ảnh - Convolution là gì?
  • Tut 9: Xử lý ảnh - Làm mờ ảnh [blur]
  • Tut 10: Xử lý ảnh - Gradient của ảnh là gì?
  • Tut 11: Xử lý ảnh - Phát hiện cạnh Canny [Canny Edge Detection]
  • Tut 12: Xử lý ảnh - Phát hiện đường thẳng bằng Hough Transform [Hough Line]
  • Tut 13: Xử lý ảnh - Hiện thực phát hiện đoạn thẳng dùng Hough Transform [Hough Line]
  • Tut 14: Xử lý ảnh - Giải thuật phân vùng Region Growing trên ảnh màu
  • Tut 15: Xử lý ảnh - Giải thuật Background Subtraction trên ảnh màu
  • Tut 16: Xử lý ảnh - Frame Subtraction để phát hiện chuyển động trong video
  • Tut 17: Xử lý ảnh - HOG - Histograms of Oriented Gradients
  • Tut 18: Xử lý ảnh - HOG - Huấn luyện mô hình phân loại người
  • Tut 19: Xử lý ảnh - HOG - Phát hiện người
  • Tut 20: Xử lý ảnh - Tổng hợp kinh nghiệm xử lý ảnh [End]
  • Tut 21: Xử lý ảnh - Hiện thực trích đặc trưng Local Binary Patterns [LBP]
  • Tut 22: Xử lý ảnh - Trích đặc trưng Gabor filters

Chủ Đề