{"id":389,"date":"2018-02-10T21:43:01","date_gmt":"2018-02-10T21:43:01","guid":{"rendered":"https:\/\/peterklemperer.com\/blog\/?p=389"},"modified":"2018-02-10T21:51:10","modified_gmt":"2018-02-10T21:51:10","slug":"manual-exposure-control-of-opencv-video","status":"publish","type":"post","link":"https:\/\/peterklemperer.com\/blog\/2018\/02\/10\/manual-exposure-control-of-opencv-video\/","title":{"rendered":"Manual Exposure Control of OpenCV Video"},"content":{"rendered":"<p>My experiments robot localization have been frustrated by blurry images. Blurry images have been making estimating the position of Aruco tag boards difficult with OpenCV. In my case, the camera is mounted to a moving robot that is photographing tags on other moving robots. Faster shutter speeds may sharpen the images and allow for better estimation.<\/p>\n<p>Controlling shutter speed was more tricky than I first imagined, so I have written this post to document my experience. This approach is very platform dependent, so even small differences may affect your success following in my footsteps.<\/p>\n<p><!--more--><\/p>\n<p>Some details of my setup:<\/p>\n<ul>\n<li>Raspberry Pi Model 3<\/li>\n<li>Raspberry Pi Camera V2 &#8211; 8 MP<\/li>\n<li>OpenCV 3<\/li>\n<li>V4L2 Capture Driver<\/li>\n<\/ul>\n<h3>TLDR; Demo Program for Controlling Exposure<\/h3>\n<pre>#!\/local\/bin\/python3 \r\n\r\nimport cv2 \r\nimport subprocess\r\n\r\n# open the capture\r\ncap = cv2.VideoCapture(0) \r\n\r\n# set the exposure after opening the capture to\r\n# avoid opencv modifying settings\r\ncommand = \"v4l2-ctl -d 0 -c auto_exposure=1 -c exposure_time_absolute=200\"\r\noutput = subprocess.call(command, shell=True)\r\n\r\n# watch your changes!\r\nwhile(True): \r\n  ret, frame = cap.read() \r\n  cv2.imshow('frame', frame) \r\n  if( cv2.waitKey(1) &amp; 0xFF == ord('q') ): \r\n    break \r\ncap.release() \r\ncv2.destroyAllWindows()<\/pre>\n<p>This program displays a stream of the camera with shutter speed of 20 milliseconds. If you want, change the exposure_time_absolute value to 400 for an exposure time of 40 milliseconds.<\/p>\n<h3>V4L2 Details<\/h3>\n<p>Install the V4L2-utils package on your system. To list the available camera controls on your system, use the following command. In my case, video0 is my preferred camera and the currently running camera in my OpenCV program.<\/p>\n<pre>$&gt; v4l2-ctl -d \/dev\/video0 --list-ctrls<\/pre>\n<p>Simply setting the\u00a0exposure_time_absolute value was insufficient, I also had to set the camera to manual exposure.<\/p>\n<pre>$&gt; v4l2-ctl -d \/dev\/video0 -c auto_exposure=1\r\n$&gt; v4l2-ctl -d \/dev\/video0 -c exposure_time_absolute=100<\/pre>\n<p>I&#8217;m still working out the units of the exposure time, but it appears to be in 100\u03bcs units.<\/p>\n<p>Other interesting settings that I will return to as I have time:<\/p>\n<ul>\n<li>iso_sensitivity_auto, (0 = manual, 1 = auto )<\/li>\n<li>iso_sensitivity, (0 = 0?, 1 = 100, 2 = 200, 3 = 400, 4 = 800)<\/li>\n<li>image_stabilization,<\/li>\n<li>exposure_metering_mode,<\/li>\n<li>scene_mode,<\/li>\n<li>compression_quality.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/ftPeter\/pose-estimation\/tree\/master\/camera-manual-exposure\">I have created a demo program here that I will use to demonstrate more parameters.<\/a><\/p>\n<p>Interpreting the meaning of the settings:<\/p>\n<pre>$&gt; v4l2-ctl --list-ctrls-menus<\/pre>\n<h3>Related Resources:<\/h3>\n<ul>\n<li><a href=\"https:\/\/picamera.readthedocs.io\/en\/release-1.13\/fov.html\">List of raspberry pi camera hardware misconceptions<\/a><\/li>\n<li><a href=\"https:\/\/picamera.readthedocs.io\/en\/release-1.13\/recipes1.html\">Raspicam<\/a><\/li>\n<li><a href=\"http:\/\/pythonexample.com\/code\/python-v4l2-ctl\/\">V4L2 Library for Python Examples<\/a>\n<ul>\n<li>Installation (sudo pip3 install v4l2)<\/li>\n<li>import v4l2 fails in python3<\/li>\n<li><a href=\"https:\/\/bugs.launchpad.net\/python-v4l2\/+bug\/1664158\">Fix with list(range(0,5))<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>My experiments robot localization have been frustrated by blurry images. Blurry images have been making estimating the position of Aruco tag boards difficult with OpenCV. In my case, the camera is mounted to a moving robot that is photographing tags &hellip; <a href=\"https:\/\/peterklemperer.com\/blog\/2018\/02\/10\/manual-exposure-control-of-opencv-video\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[6,80],"tags":[89,42,5,85,88],"class_list":["post-389","post","type-post","status-publish","format-standard","hentry","category-projects","category-robotics","tag-camera","tag-linux","tag-opencv","tag-raspberry-pi","tag-v4l2"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1VqWo-6h","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/peterklemperer.com\/blog\/wp-json\/wp\/v2\/posts\/389","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/peterklemperer.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/peterklemperer.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/peterklemperer.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/peterklemperer.com\/blog\/wp-json\/wp\/v2\/comments?post=389"}],"version-history":[{"count":0,"href":"https:\/\/peterklemperer.com\/blog\/wp-json\/wp\/v2\/posts\/389\/revisions"}],"wp:attachment":[{"href":"https:\/\/peterklemperer.com\/blog\/wp-json\/wp\/v2\/media?parent=389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/peterklemperer.com\/blog\/wp-json\/wp\/v2\/categories?post=389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/peterklemperer.com\/blog\/wp-json\/wp\/v2\/tags?post=389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}