Imshow: mức độ và khía cạnh


85

Tôi đang viết một hệ thống phần mềm trực quan hóa các lát cắt và hình chiếu thông qua tập dữ liệu 3D. Tôi đang sử dụng matplotlibvà cụ thể là imshowđể trực quan hóa bộ đệm hình ảnh mà tôi lấy lại từ mã phân tích của mình.

Vì tôi muốn chú thích các hình ảnh bằng các trục biểu đồ, nên tôi sử dụng từ khóa imshowscope cung cấp để ánh xạ tọa độ pixel đệm hình ảnh với hệ tọa độ không gian dữ liệu.

Thật matplotlibkhông may, không biết về các đơn vị. Giả sử (lấy một ví dụ nhân tạo) rằng tôi muốn vẽ một hình ảnh có kích thước là 1000 m X 1 km. Trong trường hợp đó, mức độ sẽ như thế nào [0, 1000, 0, 1]. Mặc dù mảng hình ảnh là hình vuông, vì tỷ lệ khung hình được ngụ ý bởi từ khóa scope là 1000, nên các trục của biểu đồ kết quả cũng có tỷ lệ khung hình là 1000.

Có thể ép buộc tỷ lệ co của cốt truyện trong khi vẫn giữ các dấu tích và nhãn chính được tạo tự động mà tôi nhận được bằng cách sử dụng từ khóa scope không?

Câu trả lời:


141

Bạn có thể làm điều đó bằng cách đặt khía cạnh của hình ảnh theo cách thủ công (hoặc bằng cách để nó tự động điều chỉnh tỷ lệ để lấp đầy phạm vi của hình).

Theo mặc định, imshowđặt khía cạnh của âm mưu thành 1, vì đây thường là những gì mọi người muốn cho dữ liệu hình ảnh.

Trong trường hợp của bạn, bạn có thể làm điều gì đó như:

import matplotlib.pyplot as plt
import numpy as np

grid = np.random.random((10,10))

fig, (ax1, ax2, ax3) = plt.subplots(nrows=3, figsize=(6,10))

ax1.imshow(grid, extent=[0,100,0,1])
ax1.set_title('Default')

ax2.imshow(grid, extent=[0,100,0,1], aspect='auto')
ax2.set_title('Auto-scaled Aspect')

ax3.imshow(grid, extent=[0,100,0,1], aspect=100)
ax3.set_title('Manually Set Aspect')

plt.tight_layout()
plt.show()

nhập mô tả hình ảnh ở đây


Cảm ơn. Thật buồn cười khi các tài liệu không nói gì về scalarquyền chọn. Nó dường như chia tỷ lệ y-axistheo vô hướng đã cho.
orodbhen

@JoeKington có thể lấy kích thước của các pixel riêng lẻ không. Kích thước này phụ thuộc vào kích thước của tập dữ liệu và có thể tạo thành một mảng chắp vá thành một ô liên tục như trong trường hợp của bạn.
Alexander Cska

4

Từ plt.imshow()hướng dẫn chính thức, chúng tôi biết rằng khía cạnh kiểm soát tỷ lệ khung hình của các trục. Nói cách khác, khía cạnh chính xác là tỷ lệ giữa đơn vị x và đơn vị y . Hầu hết thời gian chúng tôi muốn giữ nó là 1 vì chúng tôi không muốn làm sai lệch số liệu một cách vô ý. Tuy nhiên, thực sự có những trường hợp mà chúng ta cần chỉ định khía cạnh một giá trị khác với 1. Người hỏi đã cung cấp một ví dụ điển hình rằng trục x và y có thể có các đơn vị vật lý khác nhau. Giả sử rằng x tính bằng km và y tính bằng m. Do đó, đối với dữ liệu 10x10, phạm vi phải là [0,10km, 0,10m] = [0, 10000m, 0, 10m]. Trong trường hợp đó, nếu chúng ta tiếp tục sử dụng khía cạnh mặc định = 1, chất lượng của hình thực sự rất tệ. Do đó, chúng tôi có thể chỉ định khía cạnh = 1000 để tối ưu hóa số liệu của chúng tôi. Các mã sau đây minh họa phương pháp này.

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
rng=np.random.RandomState(0)
data=rng.randn(10,10)
plt.imshow(data, origin = 'lower',  extent = [0, 10000, 0, 10], aspect = 1000)

nhập mô tả hình ảnh ở đây

Tuy nhiên, tôi nghĩ rằng có một giải pháp thay thế có thể đáp ứng nhu cầu của người hỏi. Chúng ta chỉ có thể đặt phạm vi là [0,10,0,10] và thêm các nhãn trục xy bổ sung để biểu thị các đơn vị. Các mã như sau.

plt.imshow(data, origin = 'lower',  extent = [0, 10, 0, 10])
plt.xlabel('km')
plt.ylabel('m')

nhập mô tả hình ảnh ở đây

Để tạo ra một con số chính xác , chúng ta phải luôn ghi nhớ rằng x_max-x_min = x_res * data.shape[1]y_max - y_min = y_res * data.shape[0], ở đâu extent = [x_min, x_max, y_min, y_max]. Theo mặc định, aspect = 1nghĩa là pixel đơn vị là hình vuông. Hành vi mặc định này cũng hoạt động tốt đối với x_res và y_res có các giá trị khác nhau. Mở rộng ví dụ trước, giả sử rằng x_res là 1,5 trong khi y_res là 1. Do đó, mức độ phải bằng [0,15,0,10]. Sử dụng khía cạnh mặc định, chúng ta có thể có các pixel màu hình chữ nhật, trong khi pixel đơn vị vẫn là hình vuông!

plt.imshow(data, origin = 'lower',  extent = [0, 15, 0, 10])
# Or we have similar x_max and y_max but different data.shape, leading to different color pixel res.
data=rng.randn(10,5)
plt.imshow(data, origin = 'lower',  extent = [0, 5, 0, 5])

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Khía cạnh của pixel màu là x_res / y_res. đặt khía cạnh của nó thành khía cạnh của pixel đơn vị (tức là aspect = x_res / y_res = ((x_max - x_min) / data.shape[1]) / ((y_max - y_min) / data.shape[0])) sẽ luôn cho pixel màu vuông. Chúng ta có thể thay đổi khía cạnh = 1,5 để đơn vị trục x gấp 1,5 lần đơn vị trục y, dẫn đến pixel màu hình vuông và toàn bộ hình vuông nhưng đơn vị pixel hình chữ nhật. Rõ ràng, nó thường không được chấp nhận.

data=rng.randn(10,10)
plt.imshow(data, origin = 'lower',  extent = [0, 15, 0, 10], aspect = 1.5)

nhập mô tả hình ảnh ở đây

Trường hợp không mong muốn nhất là đặt khía cạnh một giá trị tùy ý, như 1,2, sẽ không dẫn đến pixel đơn vị hình vuông hoặc pixel màu vuông.

plt.imshow(data, origin = 'lower',  extent = [0, 15, 0, 10], aspect = 1.2)

nhập mô tả hình ảnh ở đây

Câu chuyện ngắn, luôn luôn là đủ để đặt mức độ chính xác và để matplotlib làm những việc còn lại cho chúng ta (mặc dù x_res! = Y_res)! Thay đổi khía cạnh chỉ khi nó là bắt buộc.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.