Imshow: ขอบเขตและแง่มุม


86

ฉันกำลังเขียนระบบซอฟต์แวร์ที่แสดงภาพชิ้นส่วนและเส้นโครงร่างผ่านชุดข้อมูล 3 มิติ ฉันใช้matplotlibและโดยเฉพาะimshowเพื่อแสดงภาพบัฟเฟอร์รูปภาพที่ฉันได้รับกลับมาจากโค้ดการวิเคราะห์ของฉัน

เนื่องจากฉันต้องการใส่คำอธิบายประกอบภาพด้วยแกนพล็อตฉันจึงใช้คีย์เวิร์ดขอบเขตที่imshowใช้ในการแมปพิกัดพิกเซลบัฟเฟอร์รูปภาพกับระบบพิกัดพื้นที่ข้อมูล

เคราะห์ร้ายmatplotlibไม่รู้เรื่องหน่วย Say (การเป็นตัวอย่างเทียม) 1000 m X 1 kmที่ผมอยากจะพล็อตรูปภาพที่มีขนาดของ [0, 1000, 0, 1]ในกรณีที่ว่าเท่าที่จะเป็นสิ่งที่ชอบ แม้ว่าอาร์เรย์รูปภาพจะเป็นสี่เหลี่ยมจัตุรัสเนื่องจากอัตราส่วนภาพโดยนัยของคีย์เวิร์ดขอบเขตคือ 1,000 แกนพล็อตที่ได้จะมีอัตราส่วนภาพเท่ากับ 1,000

เป็นไปได้หรือไม่ที่จะบังคับอัตราส่วนกว้างยาวของพล็อตในขณะที่ยังคงรักษาเครื่องหมายขีดและป้ายกำกับหลักที่สร้างขึ้นโดยอัตโนมัติโดยใช้คีย์เวิร์ดขอบเขต

คำตอบ:


144

คุณสามารถทำได้โดยตั้งค่าขนาดของภาพด้วยตนเอง (หรือปล่อยให้ปรับขนาดอัตโนมัติเพื่อเติมเต็มขอบเขตของภาพ)

โดยค่าเริ่มต้นimshowกำหนดลักษณะของพล็อตเป็น 1 เนื่องจากมักเป็นสิ่งที่ผู้คนต้องการสำหรับข้อมูลรูปภาพ

ในกรณีของคุณคุณสามารถทำสิ่งต่อไปนี้

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()

ใส่คำอธิบายภาพที่นี่


ขอบคุณ. ตลกที่เอกสารไม่พูดอะไรเกี่ยวกับscalarตัวเลือก ดูเหมือนว่าจะปรับขนาดy-axisตามสเกลาร์ที่กำหนด
orodbhen

@JoeKington เป็นไปได้ไหมที่จะได้ขนาดของแต่ละพิกเซล ขนาดนี้ขึ้นอยู่กับขนาดของชุดข้อมูลและสามารถสร้างการเย็บปะติดปะต่อกันของกระเบื้องเป็นพล็อตต่อเนื่องได้เช่นในกรณีของคุณ
Alexander Cska

4

จากplt.imshow()คำแนะนำอย่างเป็นทางการเราทราบดีว่าลักษณะการควบคุมอัตราส่วนภาพของแกน ดีในคำพูดของฉันด้านคือว่าอัตราส่วนของ x หน่วย y และหน่วย ส่วนใหญ่เราต้องการเก็บไว้เป็น 1 เนื่องจากเราไม่ต้องการบิดเบือนตัวเลขโดยไม่ได้ตั้งใจ อย่างไรก็ตามมีหลายกรณีที่เราจำเป็นต้องระบุค่าด้านอื่นที่ไม่ใช่ 1 ผู้ถามให้ตัวอย่างที่ดีว่าแกน x และ y อาจมีหน่วยทางกายภาพที่แตกต่างกัน สมมติว่า x มีหน่วยเป็นกม. และ y ในหน่วยเมตร ดังนั้นสำหรับข้อมูล 10x10 ควรมีขอบเขต [0,10km, 0,10m] = [0, 10000m, 0, 10m] ในกรณีเช่นนี้ถ้าเรายังคงใช้ค่าเริ่มต้น = 1 คุณภาพของรูปจะแย่มาก ดังนั้นเราสามารถระบุด้าน = 1,000 เพื่อปรับรูปของเราให้เหมาะสม รหัสต่อไปนี้แสดงให้เห็นถึงวิธีนี้

%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)

ใส่คำอธิบายภาพที่นี่

อย่างไรก็ตามฉันคิดว่ามีทางเลือกอื่นที่สามารถตอบสนองความต้องการของผู้ถามได้ เราสามารถกำหนดขอบเขตเป็น [0,10,0,10] และเพิ่มป้ายกำกับแกน xy เพิ่มเติมเพื่อแสดงหน่วย รหัสดังนี้

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

ใส่คำอธิบายภาพที่นี่

ในการสร้างหุ่นที่ถูกต้องเราควรจำไว้เสมอว่าx_max-x_min = x_res * data.shape[1]และที่y_max - y_min = y_res * data.shape[0] extent = [x_min, x_max, y_min, y_max]ตามค่าเริ่มต้นaspect = 1หมายความว่าพิกเซลของหน่วยเป็นสี่เหลี่ยมจัตุรัส ลักษณะการทำงานเริ่มต้นนี้ยังใช้ได้ดีสำหรับ x_res และ y_res ที่มีค่าต่างกัน จากตัวอย่างก่อนหน้านี้สมมติว่า x_res เท่ากับ 1.5 ในขณะที่ y_res คือ 1 ดังนั้นขอบเขตควรเท่ากับ [0,15,0,10] โดยใช้ค่าเริ่มต้นเราสามารถมีพิกเซลสีสี่เหลี่ยมในขณะที่พิกเซลของหน่วยยังคงเป็นสี่เหลี่ยมจัตุรัส!

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])

ใส่คำอธิบายภาพที่นี่ ใส่คำอธิบายภาพที่นี่

x_res / y_resด้านของพิกเซลสี การตั้งค่าลักษณะเป็นขนาดของหน่วยพิกเซล (เช่นaspect = x_res / y_res = ((x_max - x_min) / data.shape[1]) / ((y_max - y_min) / data.shape[0])) จะให้พิกเซลสีเหลี่ยมเสมอ เราสามารถเปลี่ยนด้าน = 1.5 เพื่อให้หน่วยแกน x เป็น 1.5 เท่าของหน่วยแกน y ซึ่งนำไปสู่พิกเซลสีสี่เหลี่ยมและรูปสี่เหลี่ยมจัตุรัสทั้งหมด แต่เป็นหน่วยพิกเซลสี่เหลี่ยม เห็นได้ชัดว่าปกติแล้วไม่ได้รับการยอมรับ

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

ใส่คำอธิบายภาพที่นี่

กรณีที่ไม่ต้องการมากที่สุดคือตั้งค่าตามอำเภอใจเช่น 1.2 ซึ่งจะนำไปสู่พิกเซลหน่วยสี่เหลี่ยมจัตุรัสหรือพิกเซลสีสี่เหลี่ยมจัตุรัส

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

ใส่คำอธิบายภาพที่นี่

เรื่องสั้นขนาดยาวมันเพียงพอเสมอที่จะกำหนดขอบเขตที่ถูกต้องและปล่อยให้ matplotlib ทำสิ่งที่เหลือให้เรา (แม้ว่า x_res! = y_res)! เปลี่ยนลักษณะเฉพาะเมื่อจำเป็นเท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.