ข้อมูลเบื้องต้นเกี่ยวกับการประมวลผลภาพ Python ในการถ่ายภาพด้วยคอมพิวเตอร์

เผยแพร่แล้ว: 2022-03-11

การถ่ายภาพด้วยคอมพิวเตอร์เป็นเรื่องเกี่ยวกับการปรับปรุงกระบวนการถ่ายภาพด้วยการคำนวณ ในขณะที่เรามักจะคิดว่าสิ่งนี้ใช้ได้เฉพาะกับผลลัพธ์สุดท้ายหลังการประมวลผล (คล้ายกับการแก้ไขภาพ) ความเป็นไปได้นั้นสมบูรณ์ยิ่งขึ้นเนื่องจากสามารถเปิดใช้งานการคำนวณในทุกขั้นตอนของกระบวนการถ่ายภาพ เริ่มต้นด้วยการส่องสว่างของฉาก ดำเนินการต่อด้วย เลนส์ และสุดท้ายแม้กระทั่งการแสดงภาพที่ถ่าย

นี่เป็นสิ่งสำคัญเพราะช่วยให้ทำสิ่งต่างๆ ได้มากขึ้นและแตกต่างไปจากที่สามารถทำได้ด้วยกล้องทั่วไป นอกจากนี้ยังมีความสำคัญเนื่องจากกล้องที่แพร่หลายที่สุดในปัจจุบัน—กล้องมือถือ—ไม่ได้ทรงพลังเป็นพิเศษเมื่อเทียบกับพี่น้องที่ใหญ่กว่า (DSLR) แต่ก็จัดการให้ทำงานได้ดีด้วยการควบคุมพลังการประมวลผลที่มีอยู่ในอุปกรณ์ .

เราจะมาดูตัวอย่างสองตัวอย่างที่การคำนวณสามารถปรับปรุงการถ่ายภาพ—ให้แม่นยำยิ่งขึ้น เราจะเห็นว่าการถ่ายภาพให้มากขึ้นและการใช้ Python เล็กน้อยเพื่อรวมเข้าด้วยกันสามารถสร้างผลลัพธ์ที่ดีในสองสถานการณ์ที่ฮาร์ดแวร์กล้องมือถือทำไม่ได้ได้อย่างไร เปล่งประกายอย่างแท้จริง—ในที่แสงน้อยและช่วงไดนามิกสูง

การถ่ายภาพในที่แสงน้อย

สมมติว่าเราต้องการถ่ายภาพฉากในที่แสงน้อย แต่กล้องมีรูรับแสงขนาดเล็ก (เลนส์) และเวลาในการเปิดรับแสงจำกัด นี่เป็นสถานการณ์ทั่วไปสำหรับกล้องโทรศัพท์มือถือซึ่งในที่แสงน้อยสามารถสร้างภาพเช่นนี้ได้ (ถ่ายด้วยกล้อง iPhone 6):

ภาพของเล่นคู่หนึ่งในสภาพแวดล้อมที่มีแสงน้อย

หากเราพยายามปรับปรุงคอนทราสต์ ผลลัพธ์จะเป็นดังนี้ ซึ่งค่อนข้างแย่:

ภาพเดียวกับข้างบน สว่างกว่ามาก แต่มีนอยส์รบกวนทางสายตา

เกิดอะไรขึ้น? เสียงทั้งหมดนี้มาจากไหน?

คำตอบคือเสียงรบกวนมาจากเซ็นเซอร์ ซึ่งเป็นอุปกรณ์ที่พยายามระบุเวลาที่แสงตกกระทบและความเข้มของแสง อย่างไรก็ตาม ในที่แสงน้อย จะต้องเพิ่มความไวของมันอย่างมากเพื่อลงทะเบียนทุกอย่าง และความไวสูงนั้นหมายความว่ามันจะเริ่มตรวจจับผลบวกที่ผิดพลาด—โฟตอนที่ไม่มีอยู่จริง (โปรดทราบว่าปัญหานี้ไม่ได้มีผลกับอุปกรณ์เท่านั้น แต่ยังรวมถึงมนุษย์ด้วยเช่นกัน: ครั้งต่อไปที่คุณอยู่ในห้องมืด ให้ใช้เวลาสักครู่เพื่อสังเกตเสียงรบกวนที่เกิดขึ้นในช่องมองของคุณ)

จะมีสัญญาณรบกวนจำนวนหนึ่งอยู่ในอุปกรณ์สร้างภาพเสมอ อย่างไรก็ตาม หากสัญญาณ (ข้อมูลที่เป็นประโยชน์) มีความเข้มสูง สัญญาณรบกวนจะน้อยมาก (อัตราส่วนสัญญาณต่อสัญญาณรบกวนสูง) เมื่อสัญญาณเหลือน้อย—เช่น ในที่แสงน้อย— สัญญาณรบกวนจะออกมา (สัญญาณต่ำเป็นสัญญาณรบกวน)

ถึงกระนั้น เราก็สามารถเอาชนะปัญหาจุดรบกวนได้ แม้ว่าจะมีข้อจำกัดของกล้องทั้งหมด เพื่อให้ได้ภาพที่ดีกว่าภาพด้านบน

ในการทำเช่นนั้น เราต้องคำนึงถึงสิ่งที่เกิดขึ้นเมื่อเวลาผ่านไป: สัญญาณจะยังคงเหมือนเดิม (ฉากเดิมและเราถือว่ามันเป็นสัญญาณรบกวน) ในขณะที่สัญญาณรบกวนจะถูกสุ่มโดยสมบูรณ์ ซึ่งหมายความว่าหากเราถ่ายภาพหลายๆ ภาพในฉาก ภาพเหล่านั้นจะมีจุดรบกวนในเวอร์ชันต่างๆ กัน แต่มีข้อมูลที่เป็นประโยชน์เหมือนกัน

ดังนั้น หากเราเฉลี่ยภาพจำนวนมากที่ถ่ายในช่วงเวลาหนึ่ง สัญญาณรบกวนจะตัดกันในขณะที่สัญญาณจะไม่ได้รับผลกระทบ

ภาพประกอบต่อไปนี้แสดงตัวอย่างแบบง่าย: เรามีสัญญาณ (สามเหลี่ยม) ที่ได้รับผลกระทบจากสัญญาณรบกวน และเราพยายามกู้คืนสัญญาณโดยหาค่าเฉลี่ยของสัญญาณเดียวกันหลายตัวที่ได้รับผลกระทบจากสัญญาณรบกวนที่ต่างกัน

การสาธิตสี่แผงของรูปสามเหลี่ยม รูปภาพที่กระจัดกระจายแทนรูปสามเหลี่ยมที่มีสัญญาณรบกวนเพิ่มเติม รูปสามเหลี่ยมขรุขระที่แสดงถึงค่าเฉลี่ยของ 50 ตัวอย่าง และค่าเฉลี่ย 1,000 ตัวอย่าง ซึ่งเกือบจะเหมือนกันกับสามเหลี่ยมเดิม

เราเห็นว่าแม้ว่าสัญญาณรบกวนจะรุนแรงพอที่จะบิดเบือนสัญญาณอย่างสมบูรณ์ในทุกกรณี แต่โดยเฉลี่ยแล้วจะค่อยๆ ลดเสียงรบกวนและเรากู้คืนสัญญาณดั้งเดิม

มาดูกันว่าหลักการนี้ใช้กับภาพอย่างไร: อันดับแรก เราจำเป็นต้องถ่ายภาพวัตถุหลายๆ ภาพด้วยค่าแสงสูงสุดที่กล้องอนุญาต เพื่อผลลัพธ์ที่ดีที่สุด ให้ใช้แอพที่ช่วยให้ถ่ายภาพแบบแมนนวลได้ สิ่งสำคัญคือต้องถ่ายจากตำแหน่งเดียวกัน ดังนั้นขาตั้งกล้อง (แบบชั่วคราว) จะช่วยได้

โดยทั่วไป การถ่ายภาพจำนวนมากขึ้นจะหมายถึงคุณภาพที่ดีขึ้น แต่จำนวนที่แน่นอนขึ้นอยู่กับสถานการณ์: มีแสงมากน้อยเพียงใด กล้องมีความไวเพียงใด ฯลฯ ช่วงที่ดีอาจอยู่ระหว่าง 10 ถึง 100

เมื่อเราได้ภาพเหล่านี้แล้ว (ในรูปแบบ raw ถ้าเป็นไปได้) เราสามารถอ่านและประมวลผลภาพเหล่านี้ใน Python

สำหรับผู้ที่ไม่คุ้นเคยกับการประมวลผลภาพใน Python เราควรพูดถึงว่าภาพแสดงเป็นอาร์เรย์ 2 มิติของค่าไบต์ (0-255) นั่นคือสำหรับภาพขาวดำหรือภาพสีเทา ภาพสีสามารถคิดได้ว่าเป็นชุดของภาพสามภาพ ภาพหนึ่งสำหรับแต่ละช่องสี (R, G, B) หรืออาร์เรย์ 3 มิติที่จัดทำดัชนีโดยตำแหน่งแนวตั้ง ตำแหน่งแนวนอน และช่องสี (0, 1, 2) อย่างมีประสิทธิภาพ .

เราจะใช้ประโยชน์จากสองไลบรารี: NumPy (http://www.numpy.org/) และ OpenCV (https://opencv.org/) อย่างแรกช่วยให้เราสามารถคำนวณบนอาร์เรย์ได้อย่างมีประสิทธิภาพมาก (ด้วยโค้ดที่สั้นจนน่าตกใจ) ในขณะที่ OpenCV จัดการการอ่าน/เขียนไฟล์ภาพในกรณีนี้ แต่มีความสามารถมากกว่ามาก โดยมีขั้นตอนกราฟิกขั้นสูงมากมาย ซึ่งบางขั้นตอนเราจะทำ ใช้ในภายหลังในบทความ

 import os import numpy as np import cv2 folder = 'source_folder' # We get all the image files from the source folder files = list([os.path.join(folder, f) for f in os.listdir(folder)]) # We compute the average by adding up the images # Start from an explicitly set as floating point, in order to force the # conversion of the 8-bit values from the images, which would otherwise overflow average = cv2.imread(files[0]).astype(np.float) for file in files[1:]: image = cv2.imread(file) # NumPy adds two images element wise, so pixel by pixel / channel by channel average += image # Divide by count (again each pixel/channel is divided) average /= len(files) # Normalize the image, to spread the pixel intensities across 0..255 # This will brighten the image without losing information output = cv2.normalize(average, None, 0, 255, cv2.NORM_MINMAX) # Save the output cv2.imwrite('output.png', output)

ผลลัพธ์ (เมื่อใช้คอนทราสต์อัตโนมัติ) แสดงว่าสัญญาณรบกวนหายไป ซึ่งเป็นการปรับปรุงอย่างมากจากภาพต้นฉบับ

ภาพถ่ายของเล่นเดิม คราวนี้ทั้งสว่างและชัดกว่ามาก โดยแทบไม่เห็นสัญญาณรบกวนเลย

อย่างไรก็ตาม เรายังคงสังเกตเห็นสิ่งประดิษฐ์แปลก ๆ เช่นกรอบสีเขียวและรูปแบบกริด คราวนี้ไม่ใช่เสียงสุ่ม แต่เป็นสัญญาณรบกวนรูปแบบคงที่ เกิดอะไรขึ้น?

ภาพระยะใกล้ที่มุมซ้ายบนของภาพด้านบน

ภาพระยะใกล้ของมุมบนซ้าย แสดงกรอบสีเขียวและรูปแบบตาราง

อีกครั้งเราสามารถตำหนิเซ็นเซอร์ได้ ในกรณีนี้ เราจะเห็นว่าส่วนต่างๆ ของเซ็นเซอร์ตอบสนองต่อแสงต่างกัน ส่งผลให้เกิดรูปแบบที่มองเห็นได้ องค์ประกอบบางอย่างของรูปแบบเหล่านี้เป็นเรื่องปกติและอาจเกี่ยวข้องกับพื้นผิวของเซ็นเซอร์มากที่สุด (โลหะ/ซิลิกอน) และการสะท้อน/ดูดซับโฟตอนที่เข้ามา องค์ประกอบอื่นๆ เช่น พิกเซลสีขาว เป็นเพียงพิกเซลเซ็นเซอร์ที่มีข้อบกพร่อง ซึ่งอาจมีความละเอียดอ่อนมากเกินไปหรือไม่ไวต่อแสงมากเกินไป

โชคดีที่มีวิธีกำจัดเสียงรบกวนประเภทนี้ด้วย เรียกว่าการลบเฟรมมืด

ในการทำเช่นนั้น เราจำเป็นต้องมีภาพของรูปแบบสัญญาณรบกวน และสิ่งนี้สามารถเกิดขึ้นได้หากเราถ่ายภาพความมืด ใช่ ถูกต้อง เพียงปิดรูกล้องและถ่ายภาพจำนวนมาก (เช่น 100) ด้วยเวลาเปิดรับแสงสูงสุดและค่า ISO แล้วประมวลผลตามที่อธิบายไว้ข้างต้น

เมื่อหาค่าเฉลี่ยของเฟรมสีดำหลายๆ ภาพ (ซึ่งจริงๆ แล้วไม่ใช่สีดำ เนื่องจากสัญญาณรบกวนแบบสุ่ม) เราจะลงเอยด้วยสัญญาณรบกวนรูปแบบคงที่ เราสามารถสันนิษฐานได้ว่าจุดรบกวนคงที่นี้จะคงที่ ดังนั้นขั้นตอนนี้จึงจำเป็นเพียงครั้งเดียว: ภาพที่ได้จะถูกนำมาใช้ซ้ำสำหรับภาพที่มีแสงน้อยในอนาคตทั้งหมด

นี่คือลักษณะที่ส่วนบนขวาของสัญญาณรบกวนรูปแบบ (ปรับความคมชัด) สำหรับ iPhone 6:

รูปแบบสัญญาณรบกวนสำหรับส่วนของเฟรมที่แสดงในภาพก่อนหน้า

อีกครั้ง เราสังเกตเห็นพื้นผิวเหมือนเส้นตาราง และแม้กระทั่งสิ่งที่ดูเหมือนจะเป็นพิกเซลสีขาวที่ติดอยู่

เมื่อเรามีค่าของสัญญาณรบกวนจากเฟรมมืดแล้ว (ในตัวแปร average_noise ) เราก็สามารถลบมันออกจากช็อตของเราได้ก่อนที่จะทำให้เป็นมาตรฐาน:

 average -= average_noise output = cv2.normalize(average, None, 0, 255, cv2.NORM_MINMAX) cv2.imwrite('output.png', output)

นี่คือภาพสุดท้ายของเรา:

อีกภาพครับ คราวนี้ไม่มีหลักฐานว่าถ่ายในที่แสงน้อยเลย

ช่วงไดนามิกสูง

ข้อจำกัดอีกประการหนึ่งของกล้องขนาดเล็ก (มือถือ) คือช่วงไดนามิกที่เล็ก ซึ่งหมายความว่าช่วงความเข้มของแสงที่สามารถจับภาพรายละเอียดได้ค่อนข้างเล็ก

กล่าวอีกนัยหนึ่ง กล้องสามารถจับภาพเฉพาะช่วงความเข้มของแสงที่แคบจากฉากหนึ่งเท่านั้น ความเข้มใต้แถบนั้นปรากฏเป็นสีดำล้วน ในขณะที่ความเข้มที่อยู่เหนือแถบนั้นปรากฏเป็นสีขาวบริสุทธิ์ และรายละเอียดใดๆ จะหายไปจากบริเวณเหล่านั้น

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

แต่นี่เป็นการประนีประนอม รายละเอียดหลายอย่างไม่สามารถทำให้เป็นภาพสุดท้ายได้ ในภาพสองภาพด้านล่าง เราจะเห็นฉากเดียวกันที่ถ่ายด้วยเวลาเปิดรับแสงที่ต่างกัน: การเปิดรับแสงที่สั้นมาก (1/1000 วินาที) การเปิดรับแสงปานกลาง (1/50 วินาที) และการเปิดรับแสงนาน (1/4 วินาที)

ภาพดอกไม้เดียวกันสามแบบ รุ่นหนึ่งมืดมากจนภาพส่วนใหญ่เป็นสีดำ ภาพหนึ่งดูธรรมดาถึงแม้จะมีแสงน้อย และรุ่นที่สามมีแสงสูงจนยากที่จะเห็นดอกไม้ใน เบื้องหน้า

อย่างที่คุณเห็น ทั้ง 3 ภาพไม่สามารถเก็บรายละเอียดทั้งหมดที่มีได้: เส้นใยของหลอดไฟมองเห็นได้เฉพาะในช็อตแรก และรายละเอียดของดอกไม้บางส่วนสามารถมองเห็นได้ในระยะกลางหรือภาพสุดท้าย แต่ไม่ ทั้งสอง.

ข่าวดีก็คือมีบางสิ่งที่เราสามารถทำได้เกี่ยวกับมัน และอีกครั้งที่เกี่ยวข้องกับการสร้างหลายช็อตด้วยโค้ด Python เล็กน้อย

แนวทางที่เราจะใช้ขึ้นอยู่กับงานของ Paul Debevec et al. ซึ่งอธิบายวิธีการนี้ในบทความของเขา วิธีการทำงานดังนี้:

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

ขั้นต่อไป ใช้อัลกอริทึมเพื่อสร้างเส้นโค้งการตอบสนองของกล้องขึ้นใหม่โดยพิจารณาจากสีของพิกเซลเดียวกันในช่วงเวลาการรับแสงที่ต่างกัน โดยพื้นฐานแล้วทำให้เราสร้างแผนที่ระหว่างความสว่างของฉากจริงของจุดหนึ่งๆ เวลาเปิดรับแสง และค่าที่พิกเซลที่เกี่ยวข้องจะมีในภาพที่ถ่าย เราจะใช้วิธีการของ Debevec จากไลบรารี OpenCV

 # Read all the files with OpenCV files = ['1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg'] images = list([cv2.imread(f) for f in files]) # Compute the exposure times in seconds exposures = np.float32([1. / t for t in [1000, 500, 100, 50, 10]]) # Compute the response curve calibration = cv2.createCalibrateDebevec() response = calibration.process(images, exposures)

เส้นโค้งการตอบสนองมีลักษณะดังนี้:

กราฟที่แสดงเส้นโค้งการตอบสนองเป็นการเปิดรับพิกเซล (บันทึก) เหนือค่าพิกเซล

บนแกนแนวตั้ง เรามีผลสะสมของความสว่างฉากของจุดหนึ่งและเวลาเปิดรับแสง ในขณะที่บนแกนนอน เรามีค่า (0 ถึง 255 ต่อช่องสัญญาณ) พิกเซลที่เกี่ยวข้องกัน

เส้นโค้งนี้ช่วยให้เราดำเนินการย้อนกลับได้ (ซึ่งเป็นขั้นตอนต่อไปในกระบวนการ) เมื่อพิจารณาจากค่าพิกเซลและเวลาเปิดรับแสง เราสามารถคำนวณความสว่างที่แท้จริงของแต่ละจุดในฉากได้ ค่าความสว่างนี้เรียกว่าการฉายรังสี ซึ่งจะวัดปริมาณพลังงานแสงที่ตกกระทบต่อหน่วยของพื้นที่เซ็นเซอร์ ข้อมูลนี้แสดงโดยใช้ตัวเลขทศนิยมซึ่งแตกต่างจากข้อมูลรูปภาพ เนื่องจากสะท้อนถึงช่วงค่าที่กว้างกว่ามาก (จึงเป็นช่วงไดนามิกสูง) เมื่อได้ภาพฉายรังสีแล้ว (ภาพ HDR) ก็สามารถบันทึกได้ดังนี้

 # Compute the HDR image merge = cv2.createMergeDebevec() hdr = merge.process(images, exposures, response) # Save it to disk cv2.imwrite('hdr_image.hdr', hdr)

สำหรับพวกเราที่โชคดีพอที่จะมีจอแสดงผล HDR (ซึ่งมีมากขึ้นเรื่อย ๆ ) อาจเป็นไปได้ที่จะเห็นภาพนี้โดยตรงในทุกความรุ่งโรจน์ น่าเสียดายที่มาตรฐาน HDR ยังอยู่ในช่วงเริ่มต้น ดังนั้นขั้นตอนในการดำเนินการจึงอาจแตกต่างกันบ้างสำหรับจอแสดงผลต่างๆ

สำหรับพวกเราที่เหลือ ข่าวดีก็คือเรายังคงสามารถใช้ประโยชน์จากข้อมูลนี้ได้ แม้ว่าการแสดงผลปกติจะต้องใช้รูปภาพที่มีช่องค่าไบต์ (0-255) ก็ตาม แม้ว่าเราจำเป็นต้องละทิ้งความสมบูรณ์ของแผนที่การฉายรังสีบางส่วน อย่างน้อยเราก็สามารถควบคุมวิธีที่จะทำได้

กระบวนการนี้เรียกว่าการทำแผนที่โทนสีและเกี่ยวข้องกับการแปลงแผนที่การฉายรังสีจุดลอยตัว (ที่มีค่าช่วงสูง) เป็นรูปภาพค่าไบต์มาตรฐาน มีเทคนิคในการทำเช่นนี้เพื่อให้เก็บรายละเอียดเพิ่มเติมไว้มากมาย เพียงเพื่อให้คุณเห็นตัวอย่างวิธีการทำงาน ลองนึกภาพว่าก่อนที่เราจะบีบช่วงจุดลอยตัวเป็นค่าไบต์ เราปรับปรุง (ทำให้คมชัด) ขอบที่ปรากฏในภาพ HDR การปรับปรุงขอบเหล่านี้จะช่วยรักษาขอบเหล่านี้ไว้ (และโดยนัยในรายละเอียดที่ให้ไว้) ในภาพช่วงไดนามิกต่ำ

OpenCV มีชุดของตัวดำเนินการจับคู่โทนเสียงเหล่านี้ เช่น Drago, Durand, Mantiuk หรือ Reinhardt นี่คือตัวอย่างวิธีการใช้ตัวดำเนินการเหล่านี้ (Durand) และผลลัพธ์ที่ได้

 durand = cv2.createTonemapDurand(gamma=2.5) ldr = durand.process(hdr) # Tonemap operators create floating point images with values in the 0..1 range # This is why we multiply the image with 255 before saving cv2.imwrite('durand_image.png', ldr * 255) 

ผลลัพธ์ของการคำนวณข้างต้นแสดงเป็นภาพ

เมื่อใช้ Python คุณสามารถสร้างโอเปอเรเตอร์ของคุณเองได้หากต้องการควบคุมกระบวนการเพิ่มเติม ตัวอย่างเช่น นี่คือผลลัพธ์ที่ได้จากตัวดำเนินการแบบกำหนดเอง ซึ่งจะลบความเข้มที่แสดงเป็นพิกเซลน้อยมากก่อนที่จะลดช่วงค่าลงเหลือ 8 บิต (ตามด้วยขั้นตอนคอนทราสต์อัตโนมัติ):

ภาพที่เกิดจากการทำตามขั้นตอนข้างต้น

และนี่คือรหัสสำหรับตัวดำเนินการด้านบน:

 def countTonemap(hdr, min_fraction=0.0005): counts, ranges = np.histogram(hdr, 256) min_count = min_fraction * hdr.size delta_range = ranges[1] - ranges[0] image = hdr.copy() for i in range(len(counts)): if counts[i] < min_count: image[image >= ranges[i + 1]] -= delta_range ranges -= delta_range return cv2.normalize(image, None, 0, 1, cv2.NORM_MINMAX)

บทสรุป

เราได้เห็นแล้วว่าด้วย Python เล็กน้อยและไลบรารีที่รองรับสองสามตัว เราสามารถผลักดันขีดจำกัดของกล้องจริงเพื่อปรับปรุงผลลัพธ์สุดท้าย ทั้งสองตัวอย่างที่เราได้พูดคุยกันใช้ช็อตคุณภาพต่ำหลายๆ ภาพเพื่อสร้างสิ่งที่ดีกว่า แต่ยังมีแนวทางอื่นๆ อีกมากมายสำหรับปัญหาและข้อจำกัดที่แตกต่างกัน

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

หากคุณสนใจในการคำนวณภาพบนอุปกรณ์มือถือ ให้ดูบทช่วยสอน OpenCV: การตรวจจับวัตถุแบบเรียลไทม์โดยใช้ MSER ใน iOS โดยเพื่อน Toptaler และผู้พัฒนา OpenCV ชั้นนำ Altaibayar Tseveenbayar