为什么摄像头会把竖直的物体拍成弯曲的

本文针对客户反馈的无人机拍摄垂直物体出现弯曲的问题进行了分析。通过对比静止与飞行状态下的拍摄效果,确认了该现象是由无人机快速抖动造成的。进一步地,通过回顾卷帘快门与全局快门的相关原理,解释了造成这一视觉畸变的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        最近客户反馈,我们的无人机会把竖直的物体拍成弯曲的。看到图后的第一反应就觉得这张图应该是在飞行的过程中拍摄的,且因为飞机的快速抖动导致拍摄的物体弯曲。所以就让客户在静止和飞行过程中分别拍照对比。正如我所猜测,静止拍摄时不会有问题。客户反馈的样张如下:

   对于看图后,为何有此第一反应。是因为之前有看到过一篇卷帘快门与全局快门的文章。但具体的细节记的不太清楚,所以在此再回顾一下。帖上此文章的地址:

   http://www.nphoto.net/news/2012-09/25/858d44e576553cc0.shtml

  此文很清楚的描述了细节,也配有非常有趣的视频。


# 导入必要的模块 Import required modules import time, os, sys from media.sensor import * from media.display import * from media.media import * # 图像分辨率设置 Image resolution settings PICTURE_WIDTH = 400 PICTURE_HEIGHT = 240 # 摄像头配置 Camera configuration sensor = None # 显示模式选择 Display mode selection # 可选: "VIRT", "LCD" # Options: "VIRT"(Virtual Display), "LCD" DISPLAY_MODE = "LCD" # 根据显示模式设置分辨率 Set resolution based on display mode if DISPLAY_MODE == "VIRT": DISPLAY_WIDTH = ALIGN_UP(1920, 16) DISPLAY_HEIGHT = 1080 elif DISPLAY_MODE == "LCD": DISPLAY_WIDTH = 640 DISPLAY_HEIGHT = 480 else: raise ValueError("Unknown DISPLAY_MODE, please select 'VIRT', 'LCD'") # 创建时钟对象用于FPS计算 Create clock object for FPS calculation clock = time.clock() try: # 初始化摄像头 Initialize camera sensor = Sensor() sensor.reset() # 设置图像分辨率格式 Set image resolution and format sensor.set_framesize(width=PICTURE_WIDTH, height=PICTURE_HEIGHT, chn=CAM_CHN_ID_0) sensor.set_pixformat(Sensor.RGB565, chn=CAM_CHN_ID_0) # 初始化显示器 Initialize display if DISPLAY_MODE == "VIRT": Display.init(Display.VIRT, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, fps=60) elif DISPLAY_MODE == "LCD": Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True) # 初始化媒体管理器 Initialize media manager MediaManager.init() sensor.run() while True: os.exitpoint() clock.tick() # 开始计时 Start timing # 捕获图像 Capture image img = sensor.snapshot(chn=CAM_CHN_ID_0) print("【矩形信息 Line Statistics Start】") for r in img.find_rects(threshold =5000): img.draw_rectangle(r.rect(), color = (40, 167, 225),thickness=2) for p in r.corners(): img.draw_circle(p[0], p[1], 8, color = (78, 90, 34)) print(r) print("【==============================】") # 显示FPS Display FPS print(f"FPS: {clock.fps()}") # 居中显示图像 Display image centered x = int((DISPLAY_WIDTH - PICTURE_WIDTH) / 2) y = int((DISPLAY_HEIGHT - PICTURE_HEIGHT) / 2) Display.show_image(img, x=x, y=y) except KeyboardInterrupt as e: print("User Stop: ", e) except BaseException as e: print(f"Exception: {e}") finally: # 清理资源 Cleanup resources if isinstance(sensor, Sensor): sensor.stop() Display.deinit() os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) time.sleep_ms(100) MediaManager.deinit() import time, os, sys, gc from media.sensor import * from media.display import * from media.media import * # 设置图像捕获分辨率 / Set image capture resolution SENSOR_WIDTH = 1280 SENSOR_HEIGHT = 960 FRAME_WIDTH = 640 FRAME_HEIGHT = 480 # 显示屏分辨率 / Display resolution DISPLAY_WIDTH = 640 DISPLAY_HEIGHT = 480 def init_sensor(): """初始化传感器 / Initialize sensor""" # sensor = Sensor(width=SENSOR_WIDTH, height=SENSOR_HEIGHT) # 4:3分辨率 / 4:3 resolution sensor = Sensor() sensor.reset() sensor.set_framesize(width=FRAME_WIDTH, height=FRAME_HEIGHT) # 设置帧大小 / Set frame size sensor.set_pixformat(Sensor.GRAYSCALE) # 灰度图像格式 / Grayscale format return sensor def init_display(): """初始化显示器 / Initialize display""" # 初始化屏幕 / Initialize screen Display.init(Display.ST7701, to_ide=True) # 虚拟显示配置(已注释) / Virtual display config (commented) # Display.init(Display.VIRT, sensor.width(), sensor.height()) def process_image(img): """处理图像 / Process image""" # Canny边缘检测 / Canny edge detection img.find_edges(image.EDGE_CANNY, threshold=(50, 80)) # 简单边缘检测配置 / Simple edge detection config # img.find_edges(image.EDGE_SIMPLE, threshold=(100, 255)) def main(): try: # 初始化设备 / Initialize devices sensor = init_sensor() init_display() MediaManager.init() sensor.run() # 初始化时钟 / Initialize clock clock = time.clock() # 计算显示偏移量以居中显示 / Calculate display offsets for center alignment x_offset = round((DISPLAY_WIDTH - FRAME_WIDTH) / 2) y_offset = round((DISPLAY_HEIGHT - FRAME_HEIGHT) / 2) while True: clock.tick() # 更新时钟 / Update clock # 捕获处理图像 / Capture and process image img = sensor.snapshot() process_image(img) # 居中显示图像 / Display image in center Display.show_image(img, x=x_offset, y=y_offset) # 显示FPS / Display FPS print(clock.fps()) except KeyboardInterrupt as e: print("用户中断 / User interrupted: ", e) except Exception as e: print(f"发生错误 / Error occurred: {e}") finally: # 清理资源 / Cleanup resources if 'sensor' in locals() and isinstance(sensor, Sensor): sensor.stop() Display.deinit() MediaManager.deinit() gc.collect() # 垃圾回收 / Garbage collection if __name__ == "__main__": main() import time, os, sys from media.sensor import * from media.display import * from media.media import * # 设置图像捕获分辨率 / Set picture capture resolution PICTURE_WIDTH = 400 PICTURE_HEIGHT = 240 # 显示模式:"VIRT"用于无屏幕情况,"LCD"用于有屏幕情况 # Display mode: "VIRT" for virtual display, "LCD" for physical screen DISPLAY_MODE = "LCD" # 根据显示模式设置显示分辨率 / Set display resolution based on mode if DISPLAY_MODE == "VIRT": # 虚拟显示器模式(1920x1080) / Virtual display mode DISPLAY_WIDTH = ALIGN_UP(1920, 16) # 确保宽度16字节对齐 / Ensure width is 16-byte aligned DISPLAY_HEIGHT = 1080 elif DISPLAY_MODE == "LCD": DISPLAY_WIDTH = 640 DISPLAY_HEIGHT = 480 else: raise ValueError("未知的显示模式,请选择 'VIRT' 或 'LCD' / Unknown display mode, please choose 'VIRT' or 'LCD'") def init_sensor(): """初始化传感器 / Initialize sensor""" sensor = Sensor(id=2) sensor.reset() sensor.set_framesize(width=PICTURE_WIDTH, height=PICTURE_HEIGHT, chn=CAM_CHN_ID_0) sensor.set_pixformat(Sensor.RGB565, chn=CAM_CHN_ID_0) return sensor def init_display(): """初始化显示器 / Initialize display""" if DISPLAY_MODE == "VIRT": Display.init(Display.VIRT, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, fps=60) elif DISPLAY_MODE == "LCD": Display.init(Display.ST7701, width=DISPLAY_WIDTH, height=DISPLAY_HEIGHT, to_ide=True) def process_circles(img, circles): """处理检测到的圆形 / Process detected circles""" print("【圆形信息 / Circle Statistics Start】") for i, circle in enumerate(circles): # 使用蓝色绘制圆形 / Draw circles in blue img.draw_circle(circle.circle(), color=(40,167,225), thickness=3) print(f"Circle {i}: {circle}") print("【==============================】") def main(): try: # 初始化设备 / Initialize devices sensor = init_sensor() init_display() MediaManager.init() sensor.run() # 计算显示偏移量以居中显示 / Calculate display offsets for center alignment x_offset = (DISPLAY_WIDTH - PICTURE_WIDTH) // 2 y_offset = (DISPLAY_HEIGHT - PICTURE_HEIGHT) // 2 while True: os.exitpoint() # 捕获图像 / Capture image img = sensor.snapshot(chn=CAM_CHN_ID_0) # 寻找并处理圆形 / Find and process circles # threshold: 控制圆形检测的阈值,更高的值会减少检测到的圆形数量 # threshold: Controls circle detection sensitivity, higher values reduce the number of detected circles circles = img.find_circles(threshold=3500) process_circles(img, circles) # 居中显示图像 / Display image in center Display.show_image(img, x=x_offset, y=y_offset) except KeyboardInterrupt as e: print("用户中断 / User interrupted: ", e) except Exception as e: print(f"发生错误 / Error occurred: {e}") finally: # 清理资源 / Cleanup resources if 'sensor' in locals() and isinstance(sensor, Sensor): sensor.stop() Display.deinit() os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) time.sleep_ms(100) MediaManager.deinit() if __name__ == "__main__": main() 根据上面三个程序写识别圆柱的程序
07-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值