5.21. การปรับขนาด, การพลิก, และการตัดภาพ¶
หัวข้อย่อยก่อนหน้าทั้งหมดทำงานกับพิกเซลที่ตำแหน่งเดิมที่เริ่มต้น กลุ่ม transform เปลี่ยนแปลงสิ่งนั้น การปรับขนาดส่งพิกเซลอินพุตทุกตัวไปยังตำแหน่งเอาต์พุต ที่แตกต่างกัน อาจส่งไปยังหลายตำแหน่งพร้อมกัน (เมื่อขยายขนาด) หรือไปยังตำแหน่งที่ใช้ร่วมกับพิกเซลอินพุตอื่นๆ หลายตัว (เมื่อลดขนาด) การพลิกและการหมุนทำสิ่งเดียวกันผ่านการแมปที่แตกต่างกัน การตัดภาพจะเก็บพิกเซลอินพุตส่วนย่อยสี่เหลี่ยมและทิ้งส่วนที่เหลือ
โมดูล image เปิดเผยกลุ่มนั้นผ่านสามวิธีที่แบ่งปันอาร์กิวเมนต์และพฤติกรรมส่วนใหญ่:
copy()-- สร้างสำเนาของภาพ อาจมีการปรับขนาด ตัด หรือปรับทิศทางcrop()-- การดำเนินการเดียวกับcopyแต่ด้วยความคาดหวังว่าแอปพลิเคชันจะเลือกส่วนสี่เหลี่ยมย่อยออกจากแหล่งที่มาscale()-- เหมือนกันอีกครั้ง โดยมีความคาดหวังว่าแอปพลิเคชันจะปรับขนาดผลลัพธ์
ทั้งสามใช้อาร์กิวเมนต์เดียวกันและเครื่องจักรการแปลงเดียวกัน ความแตกต่างคือที่ที่ผลลัพธ์ลงจอดตามค่าเริ่มต้น copy() สร้างภาพใหม่ ในขณะที่ crop() และ scale() แก้ไขแหล่งที่มาในที่
5.21.2. การสอดแทรก: AREA, BILINEAR, BICUBIC¶
เมื่อการปรับขนาดส่งพิกเซลเอาต์พุตแต่ละตัวไปยังตำแหน่งที่ไม่ตรงกับพิกเซลอินพุตใดตัวเดียว วิธีการต้องเลือกค่าที่จะเขียน แฟล็กสามตัวควบคุมวิธีการ:
image.BILINEAR สอดแทรกระหว่างพิกเซลอินพุตที่ใกล้ที่สุดสี่ตัวโดยถ่วงน้ำหนักด้วยระยะห่างจากตำแหน่งเอาต์พุต ผลลัพธ์จะเรียบกว่าแบบ nearest-neighbour โดยไม่มีรอยหยักที่มองเห็นบนเส้นทแยงมุม แต่การคำนวณเพิ่มเติมมีค่าใช้จ่ายประมาณสี่เท่าของการผ่าน nearest-neighbour เหมาะสำหรับงานขยายขนาดส่วนใหญ่และสำหรับตัวประกอบขนาดที่ไม่ใช่จำนวนเต็มใดๆ
image.BICUBIC สอดแทรกระหว่างพิกเซลอินพุตที่ใกล้ที่สุดสิบหกตัวโดยใช้เส้นโค้งลูกบาศก์ ซึ่งให้ผลลัพธ์ที่เรียบกว่าด้วยค่าใช้จ่ายในการคำนวณที่มากขึ้นอีก คุณภาพดีที่สุดสำหรับแอปพลิเคชันที่คำนึงถึงต้นทุนที่ต้องการ แทบไม่คุ้มกับการคำนวณเพิ่มเติมสำหรับเฟรมสดที่ IDE จะแสดงเท่านั้น
image.AREA เฉลี่ยพิกเซลอินพุตทุกตัวที่ตกอยู่ภายใน footprint ของพิกเซลเอาต์พุต -- อัลกอริทึมที่เหมาะสมสำหรับ การลดขนาด Bilinear และ bicubic เป็นตัวสอดแทรก: พวกมันประเมินค่า ระหว่าง พิกเซลต้นฉบับ ซึ่งเป็นสิ่งที่การขยายขนาดต้องการ แต่เมื่อลดขนาด พิกเซลเอาต์พุตแต่ละตัวครอบคลุมพิกเซลต้นฉบับหลายตัว และตัวสอดแทรกจะอ่านเฉพาะตัวที่ใกล้ที่สุดไม่กี่ตัว -- รายละเอียดที่ข้ามไปจะกลับมาเป็น aliasing image.AREA นำพิกเซลที่ครอบคลุมทุกตัวมาเฉลี่ยแทน
อัลกอริทึมการปรับขนาดเริ่มต้นโดยไม่มี hint คือ nearest-neighbour ซึ่งถูกที่สุดและเป็นคำตอบที่ถูกต้องเมื่อแหล่งที่มาอยู่ที่ความละเอียดพิกเซลของปลายทางอยู่แล้ว
5.21.3. ทิศทาง: การพลิกและการหมุน¶
แฟล็กทิศทางเป็นชุดการแปลงบูลีนขนาดเล็กที่ประกอบกันได้อย่างอิสระทั้งกับกันเองและกับแฟล็ก interpolation:
image.VFLIPพลิกภาพในแนวตั้ง (บนกลายเป็นล่าง)image.HMIRRORสะท้อนภาพในแนวนอน (ซ้ายกลายเป็นขวา)image.TRANSPOSEสลับแกน x และ y (แถวกลายเป็นคอลัมน์)
การหมุนส่วนใหญ่มาจากการประกอบสามตัวนั้น โมดูลยังเปิดเผยชื่อย่อ:
image.ROTATE_90(=VFLIP | TRANSPOSE)image.ROTATE_180(=HMIRROR | VFLIP)image.ROTATE_270(=HMIRROR | TRANSPOSE)
ในโค้ด:
img.copy(hint=image.ROTATE_90, copy_to_fb=True)
5.21.4. การจัดการสัดส่วนภาพ¶
เมื่อสัดส่วนภาพของแหล่งที่มาไม่ตรงกับสี่เหลี่ยมที่กำลังวาดเข้าไป แฟล็กสามตัวจะตัดสินว่าจะทำอะไรกับความไม่ตรงกันนั้น:
image.SCALE_ASPECT_KEEP รักษาสัดส่วนภาพของแหล่งที่มาและ letterboxes ผลลัพธ์ -- แหล่งที่มาถูกปรับขนาดจนพอดีภายในปลายทาง โดยมีพิกเซลว่างเปล่า (ศูนย์) เติมส่วนที่เหลือของปลายทาง เหมาะสมเมื่อการรักษาแหล่งที่มาไม่บิดเบี้ยวมีความสำคัญกว่าการเติมเอาต์พุตทั้งหมด
image.SCALE_ASPECT_EXPAND รักษาสัดส่วนภาพของแหล่งที่มาและ ตัด มัน -- แหล่งที่มาถูกปรับขนาดจนเต็มปลายทาง โดยส่วนที่เกินปลายทางจะถูกตัดออก เหมาะสมเมื่อการเติมเอาต์พุตทั้งหมดมีความสำคัญกว่าการเห็นทุกส่วนของแหล่งที่มา
image.SCALE_ASPECT_IGNORE ละเว้นสัดส่วนภาพและยืดแหล่งที่มาเพื่อเติมปลายทาง โดยยอมรับความบิดเบี้ยวใดก็ตามที่เกิดขึ้น เหมาะสมเมื่อแอปพลิเคชันได้คำนึงถึงความบิดเบี้ยวแล้ว -- เช่น เมื่อขนาดของปลายทางไม่ใช่สี่เหลี่ยมของฉากเดียวกันจริงๆ
ค่าเริ่มต้น (ไม่มีแฟล็ก aspect ตั้งค่า) เหมือนกับ SCALE_ASPECT_IGNORE: ยืดเพื่อเติม แอปพลิเคชันที่ใส่ใจสัดส่วนภาพจะระบุหนึ่งในสามตัวอย่างชัดเจน
5.21.5. เมื่อใดควรใช้อะไร¶
การปรับขนาดส่วนใหญ่ใช้ scale() กับคู่ x_scale / y_scale และ hint การสอดแทรก:
img.scale(x_scale=0.5, y_scale=0.5, hint=image.AREA)
การหมุนส่วนใหญ่ใช้การเรียกเดียวกันกับ hint=image.ROTATE_90 หรือที่คล้ายกัน
การตัดภาพใช้ crop() กับ roi ที่ไม่ใช่ค่าเริ่มต้น:
img.crop(roi=(40, 30, 200, 150))
เมื่อแหล่งที่มาต้องรอดจากการดำเนินการ -- การจับเฟรมอ้างอิง การสร้างภาพย่อของเฟรมที่กำลังจะถูกประมวลผลอย่างทำลาย -- copy() สร้างผลลัพธ์เป็นภาพใหม่และปล่อยให้แหล่งที่มาไม่เปลี่ยนแปลง:
thumbnail = img.copy(x_scale=0.25, y_scale=0.25, hint=image.AREA)
ค่าเริ่มต้นนั้นคือความแตกต่างที่แท้จริงเบื้องหลังชื่อทั้งสาม: scale และ crop แปลงในที่ copy จัดสรร คีย์เวิร์ดการวางผลลัพธ์เชื่อมช่องว่าง: copy=True บน scale หรือ crop จัดสรรผลลัพธ์เป็น heap buffer แยกต่างหากแทนที่จะเขียนทับแหล่งที่มา และ copy_to_fb=True บนทั้งสามตัวจะวางไว้ในบัฟเฟอร์เฟรมสำหรับการแสดงตัวอย่างใน IDE