{"id":8222,"date":"2015-05-10T13:58:59","date_gmt":"2015-05-10T11:58:59","guid":{"rendered":"http:\/\/lukse.lt\/uzrasai\/?p=8222"},"modified":"2015-05-10T19:38:17","modified_gmt":"2015-05-10T17:38:17","slug":"lightning-strikes-and-python","status":"publish","type":"post","link":"https:\/\/lukse.lt\/uzrasai\/2015-05-lightning-strikes-and-python\/","title":{"rendered":"Lightning strikes and Python"},"content":{"rendered":"<p style=\"text-align: justify;\"><a href=\"http:\/\/lukse.lt\/uzrasai\/2015-05-lightning-strikes-and-python\/\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft wp-image-8223 size-full\" src=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/Gp027304.mp4_045126_.jpg\" alt=\"Gp027304.mp4_045126_\" width=\"200\" height=\"130\" \/><\/a>I was always fascinated by lightning. Long time ago, being a teenager I shoot lightning strikes many times with some degree of success. At that time I was using my dad&#8217;s old Zenit camera. While lightnings are always the same, equipment advances very rapidly. Today I will talk about spotting interesting frames from video and detecting exact moment of strike using Python.<\/p>\n<div align=\"center\"><!--more--><\/div>\n<p>&nbsp;<\/p>\n<p style=\"text-align: justify;\">This is relatively simple task for a script &#8211; measure difference between two frames and if it exceeds predetermined value assume this is lightning. Key idea &#8211; lightning produces lots of light and alters many pixels. So, being Python and computer vision enthusiast, I wrote quick and dirty OpenCV script to find specific frames in long video to spot lightning strikes.<\/p>\n<p style=\"text-align: justify;\">It happened that script is pretty fast and processes 15minutes of raw 1080p@60 footage from GOPRO camera in 8 minutes on i7 CPU.<\/p>\n<p style=\"text-align: justify;\">Besides spotting interesting pictures it saves motion values to CSV file for further analysis using other tools. Here is how motion time-chart looks like. In general this is fast motion detection script without localization feature.<\/p>\n<p style=\"text-align: justify;\">Setup was out of the box &#8211; GOPRO 3 black action camera without any harness. It was just recording plain video. All processing was done on computer.<\/p>\n<div id=\"attachment_8228\" style=\"width: 410px\" class=\"wp-caption aligncenter\"><a onclick=\"javascript:pageTracker._trackPageview('\/downloads\/uzrasai\/wp-content\/uploads\/2015\/05\/Untitled.png');\"  href=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/Untitled.png\" rel=\"lightbox[8222]\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-8228\" class=\"wp-image-8228 size-medium\" src=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/Untitled-400x187.png\" alt=\"Untitled\" width=\"400\" height=\"187\" srcset=\"https:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/Untitled-400x187.png 400w, https:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/Untitled.png 925w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/a><p id=\"caption-attachment-8228\" class=\"wp-caption-text\">Motion chart shows 12 possible lightning strikes<\/p><\/div>\n<p style=\"text-align: justify;\">\n<h2 style=\"text-align: justify;\">Results<\/h2>\n<div id=\"attachment_8234\" style=\"width: 650px\" class=\"wp-caption aligncenter\"><a onclick=\"javascript:pageTracker._trackPageview('\/downloads\/uzrasai\/wp-content\/uploads\/2015\/05\/zaibai_i_tv_boksta.gif');\"  href=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/zaibai_i_tv_boksta.gif\" rel=\"lightbox[8222]\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-8234\" class=\"wp-image-8234 size-full\" src=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/zaibai_i_tv_boksta.gif\" alt=\"zaibai_i_tv_boksta\" width=\"640\" height=\"360\" \/><\/a><p id=\"caption-attachment-8234\" class=\"wp-caption-text\">Animated GIF &#8211; Lightning strike to TV tower<\/p><\/div>\n<div id=\"attachment_8236\" style=\"width: 650px\" class=\"wp-caption aligncenter\"><a onclick=\"javascript:pageTracker._trackPageview('\/downloads\/uzrasai\/wp-content\/uploads\/2015\/05\/out9.gif');\"  href=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/out9.gif\" rel=\"lightbox[8222]\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-8236\" class=\"wp-image-8236 size-full\" src=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/out9.gif\" alt=\"out9\" width=\"640\" height=\"360\" \/><\/a><p id=\"caption-attachment-8236\" class=\"wp-caption-text\">Animated GIF &#8211; lightning in Pa\u0161ilai\u010diai<\/p><\/div>\n<div id=\"attachment_8237\" style=\"width: 650px\" class=\"wp-caption aligncenter\"><a onclick=\"javascript:pageTracker._trackPageview('\/downloads\/uzrasai\/wp-content\/uploads\/2015\/05\/out6.gif');\"  href=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/out6.gif\" rel=\"lightbox[8222]\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-8237\" class=\"wp-image-8237 size-full\" src=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/out6.gif\" alt=\"out6\" width=\"640\" height=\"360\" \/><\/a><p id=\"caption-attachment-8237\" class=\"wp-caption-text\">Animated GIF &#8211; Lightning over Gari\u016bai<\/p><\/div>\n<div id=\"attachment_8246\" style=\"width: 410px\" class=\"wp-caption aligncenter\"><a onclick=\"javascript:pageTracker._trackPageview('\/downloads\/uzrasai\/wp-content\/uploads\/2015\/05\/Gp017304.mp4_036444_.jpg');\"  href=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/Gp017304.mp4_036444_.jpg\" rel=\"lightbox[8222]\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-8246\" class=\"wp-image-8246 size-medium\" src=\"http:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/Gp017304.mp4_036444_-400x248.jpg\" alt=\"Gp017304.mp4_036444_\" width=\"400\" height=\"248\" srcset=\"https:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/Gp017304.mp4_036444_-400x248.jpg 400w, https:\/\/lukse.lt\/uzrasai\/wp-content\/uploads\/2015\/05\/Gp017304.mp4_036444_.jpg 800w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/a><p id=\"caption-attachment-8246\" class=\"wp-caption-text\">Lightning strike to TV tower<\/p><\/div>\n<p style=\"text-align: justify;\">\n<h2>Making GIF with ImageMagick<\/h2>\n<pre>convert.exe -resize 640x360 -layers OptimizeTransparency +map -delay 15 -loop 0 gif\\*.jpg gif\\out.gif<\/pre>\n<h2>Quick and dirty Python script for motion detection<\/h2>\n<pre>import sys\r\nimport cv2\r\nimport cv2.cv as cv\r\nimport numpy as np\r\nfrom PIL import Image\r\nimport progress\r\nimport time\r\n\r\nSCALE = 0.5\r\nNOISE_CUTOFF = 5\r\nBLUR_SIZE = 3\r\n\r\nstart = time.time()\r\n\r\ndef count_diff(img1, img2):\r\n    small1 = cv2.resize(img1, (0,0), fx=SCALE, fy=SCALE)\r\n    small2 = cv2.resize(img2, (0,0), fx=SCALE, fy=SCALE)\r\n    #cv2.imshow('frame', small2)\r\n    #cv2.waitKey(1)\r\n    diff = cv2.absdiff(small1, small2)\r\n    diff = cv2.cvtColor(diff, cv2.COLOR_RGB2GRAY)\r\n    frame_delta1 = cv2.threshold(diff, NOISE_CUTOFF, 255, 3)[1]\r\n    frame_delta1_color = cv2.cvtColor(frame_delta1, cv2.COLOR_GRAY2RGB)\r\n    delta_count1 = cv2.countNonZero(frame_delta1)\r\n\r\n    return delta_count1\r\n\r\nfilename = sys.argv[1]\r\nvideo = cv2.VideoCapture(filename)\r\n\r\nnframes = (int)(video.get(cv.CV_CAP_PROP_FRAME_COUNT))\r\nwidth = (int)(video.get(cv.CV_CAP_PROP_FRAME_WIDTH))\r\nheight = (int)(video.get(cv.CV_CAP_PROP_FRAME_HEIGHT))\r\nfps= (int)(video.get(cv.CV_CAP_PROP_FPS))\r\n\r\nframe_count = 0\r\n\r\nprint \"[i] Frame size: \", width, height\r\nprint \"[i] Total frames:\", nframes\r\nprint \"[i] Fps:\", fps\r\n\r\nfff = open(filename+\".csv\", 'w')\r\n\r\nflag, frame0 = video.read()\r\ntreshold = int(sys.argv[2])\r\nstrikes = 0\r\n\r\np0 = progress.AnimatedProgressBar(end=nframes, width=80)\r\nfor f in xrange(nframes-1):\r\n    p0 + 1\r\n    p0.show_progress()\r\n\r\n    flag, frame1 = video.read()\r\n    diff1  = count_diff(frame0, frame1)\r\n    name = filename+\"_%06d.jpg\" % f\r\n\r\n    if diff1 &gt; treshold:\r\n        cv2.imwrite(name, frame1)\r\n        strikes = strikes + 1\r\n\r\n        #small = cv2.resize(frame1, (0,0), fx=SCALE, fy=SCALE)\r\n        #cv2.imshow('frame', small)\r\n        #cv2.waitKey(1)\r\n\r\n    text = str(f)+', '+str(diff1)\r\n    #print text\r\n    fff.write(text  + '\\n')\r\n    fff.flush()\r\n    frame0 = frame1\r\n\r\nfff.close()\r\nprint\r\nprint '[i] Strikes: ', strikes\r\nprint '[i] elapsed time:', time.time() - start<\/pre>\n<h2>Notes<\/h2>\n<p>GOPRO CMOS sensor has rolling shutter and has no manual exposure settings. That&#8217;s why many frames are split into dark and light areas. There a good thing to use ND filter to make exposure longer. In this way whole lightning strike will fit into frame and picture will be higher quality. Of course best option is to use global shutter camera, but it is difficult to find this kind of camera.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I was always fascinated by lightning. Long time ago, being a teenager I shoot lightning strikes many times with some degree of success. At that time I was using my dad&#8217;s old Zenit camera. While lightnings are always the same, equipment advances very rapidly. Today I will talk about spotting interesting frames from video and [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"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":[38,4,21,19,5,15],"tags":[],"class_list":["post-8222","post","type-post","status-publish","format-standard","hentry","category-in-english","category-nuotraukos","category-projektai","category-time-lapse","category-uzrasai","category-video"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p2rU5c-28C","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/lukse.lt\/uzrasai\/wp-json\/wp\/v2\/posts\/8222","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/lukse.lt\/uzrasai\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/lukse.lt\/uzrasai\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/lukse.lt\/uzrasai\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/lukse.lt\/uzrasai\/wp-json\/wp\/v2\/comments?post=8222"}],"version-history":[{"count":19,"href":"https:\/\/lukse.lt\/uzrasai\/wp-json\/wp\/v2\/posts\/8222\/revisions"}],"predecessor-version":[{"id":8247,"href":"https:\/\/lukse.lt\/uzrasai\/wp-json\/wp\/v2\/posts\/8222\/revisions\/8247"}],"wp:attachment":[{"href":"https:\/\/lukse.lt\/uzrasai\/wp-json\/wp\/v2\/media?parent=8222"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/lukse.lt\/uzrasai\/wp-json\/wp\/v2\/categories?post=8222"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/lukse.lt\/uzrasai\/wp-json\/wp\/v2\/tags?post=8222"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}