{"id":3597,"date":"2021-02-12T06:48:40","date_gmt":"2021-02-12T14:48:40","guid":{"rendered":"http:\/\/192.168.3.4\/?p=3597"},"modified":"2021-04-05T05:40:02","modified_gmt":"2021-04-05T12:40:02","slug":"camera-angular-calibration","status":"publish","type":"post","link":"https:\/\/www.cloudacm.com\/?p=3597","title":{"rendered":"Camera Angular Calibration"},"content":{"rendered":"<p>These are a couple of resources that I&#8217;ve used for RC camera information that you may find useful,<br \/>\n<a href=\"https:\/\/www.chucklohr.com\/808\/c16\/\">https:\/\/www.chucklohr.com\/808\/c16\/<\/a> and <a href=\"https:\/\/oscarliang.com\/how-to-use-808-16-keychain-camera-manual-and-wiki\/\">https:\/\/oscarliang.com\/how-to-use-808-16-keychain-camera-manual-and-wiki\/<\/a>. Those links are specific to the 808-16 key chain camera which I have used for bike rides as well as drone flights.<\/p>\n<p>There is mention about field of view measurements in the first link. It references methods used which I was not able to reliably validate. <a href=\"http:\/\/www.rcgroups.com\/forums\/showpost.php?p=22171449&amp;postcount=6843\">http:\/\/www.rcgroups.com\/forums\/showpost.php?p=22171449&amp;postcount=6843<\/a> and <a href=\"https:\/\/www.rcgroups.com\/forums\/showpost.php?p=22446815&amp;postcount=7732\">https:\/\/www.rcgroups.com\/forums\/showpost.php?p=22446815&amp;postcount=7732<\/a> both use the Pythagorean theorem. The camera and background are at fixed points that have a known value of measured distance. In the background are points with known distance values as well. Both of the examples use geometry to solve for the angle. This method would work were it not for lens distortion.<\/p>\n<p>Here is an example of a grid and the barrel distortion created by the wide angle lens.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/?attachment_id=3598\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3598 size-full\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Grid_Resized.png\" alt=\"\" width=\"970\" height=\"546\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Grid_Resized.png 970w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Grid_Resized-300x169.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Grid_Resized-768x432.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Grid_Resized-480x270.png 480w\" sizes=\"auto, (max-width: 970px) 100vw, 970px\" \/><\/a><\/p>\n<p>If I were to tally the pixel width of a grid space of 1\/2 inch in the center of the example, I get an approximated count of 72 pixels. If I do the same for an edge grid space, that value is now roughly 36 pixels. So the linear properties of the Pythagorean theorem can not be applied.<\/p>\n<p>So I found it easiest to take direct angular measurements using a protractor pattern.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/?attachment_id=3599\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3599 size-large\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Protractor_Rapporteur_Degree_V1-1024x542.jpeg\" alt=\"\" width=\"640\" height=\"339\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Protractor_Rapporteur_Degree_V1-1024x542.jpeg 1024w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Protractor_Rapporteur_Degree_V1-300x159.jpeg 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Protractor_Rapporteur_Degree_V1-768x407.jpeg 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Protractor_Rapporteur_Degree_V1-1536x813.jpeg 1536w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Protractor_Rapporteur_Degree_V1-510x270.jpeg 510w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Protractor_Rapporteur_Degree_V1.jpeg 1600w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>By placing the camera on the pattern and aligning it, I was able to reliably capture the field of view.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/?attachment_id=3600\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3600 size-large\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Angle-1024x576.png\" alt=\"\" width=\"640\" height=\"360\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Angle-1024x576.png 1024w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Angle-300x169.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Angle-768x432.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Angle-1536x864.png 1536w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Angle-480x270.png 480w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/RunCam2_1080_Video_Angle.png 1920w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>It&#8217;s fairly simple to get the horizontal field of view, in the example above it is 106 degrees. Now I can do pixel and angle calculations to determine the vertical and angular fields of view. Here are the values I got for my 808-16 camera.<\/p>\n<p>HRes: 1280 pixels<br \/>\nVRes: 720 pixels<br \/>\nHFOV: 108 degrees<\/p>\n<p>VFOV = ( HFOV \/ HRes ) x VRes<br \/>\nVFOV = ( 108 \/ 1280 ) x 720<br \/>\nVFOV = 0.084375 x 720<br \/>\nVFOV: 60.75 degrees<\/p>\n<p>ARes^2 = HRes^2 + VRes^2<br \/>\nARes^2 = 1280^2 + 720^2<br \/>\n2,156,800 = 1,638,400 + 518,400<br \/>\nARes = \u221a2,156,800<br \/>\nARes = 1,468.6 pixels<\/p>\n<p>AFOV = ( HFOV \/ HRes ) x ARes<br \/>\nAFOV = ( 108 \/ 1280 ) x 1,468.6<br \/>\nAFOV = 0.084375 x 1,468.6<br \/>\nAFOV = 123.91 degrees<\/p>\n<p>In case you missed it, I did ultimately use the Pythagorean theorem to find the angular resolution. Now I&#8217;m fairly confident I can measure the angle between 2 points in images. Lets take this photo from one of my flights.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/?attachment_id=3601\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3601 size-large\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Points-1024x576.png\" alt=\"\" width=\"640\" height=\"360\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Points-1024x576.png 1024w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Points-300x169.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Points-768x432.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Points-480x270.png 480w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Points.png 1280w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>How can I find the distance of objects from the drone?<\/p>\n<p>If I measure between 1st and 3rd base, the orange line, I get 342.374 pixels. This converts to 28.8878 degrees using this formula (.084375 x 342.374). The green line is from 3rd base to where the soccer fields center line and south center circle intersect, this comes out to be 41.5982 degrees from 493.0162 pixels. Lastly, the yellow line is from 1st base to the same point on the soccer field, this comes out to be 15.815 degrees from 187.438 pixels.<\/p>\n<p>If I open up Google Maps of the location, <a href=\"https:\/\/www.google.com\/maps\/@47.6968255,-122.380558,225m\/data=!3m1!1e3?hl=en\">https:\/\/www.google.com\/maps\/@47.6968255,-122.380558,225m\/data=!3m1!1e3?hl=en<\/a>, I can measure distances between those points. Those measurements are in the image above.<\/p>\n<p>I have marked a center point with a blue cross containing a red center. Here we can determine the angles from center to those points.<\/p>\n<p>1st base = 14.408 degrees<br \/>\n3rd base = 15.300 degrees<br \/>\nsoccer field = 29.103 degrees<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/?attachment_id=3602\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3602 size-large\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_FromCenter-1024x576.png\" alt=\"\" width=\"640\" height=\"360\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_FromCenter-1024x576.png 1024w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_FromCenter-300x169.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_FromCenter-768x432.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_FromCenter-480x270.png 480w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_FromCenter.png 1280w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>Using the Pythagorean theorem here still presents a problem, the center point and observed points aren&#8217;t on a level plane. Although we can theorize it forms a right angle, we can&#8217;t measure distance as we did before because the center point in the photo is on the drone.<\/p>\n<p>Measuring the distance of the drone (camera) to those points also involves some further knowledge, see <a href=\"https:\/\/www.scantips.com\/lights\/subjectdistance.html\">https:\/\/www.scantips.com\/lights\/subjectdistance.html<\/a>. In order to use the provided formula, we would need to know specific characteristics of the camera, namely sensor dimension and focal length. Additionally, the field of dimension needs to be at a right angle (perpendicular) to the camera. See <a href=\"http:\/\/gsp.humboldt.edu\/OLM\/Courses\/GSP_216_Online\/lesson2-2\/photogrammetry.html\">http:\/\/gsp.humboldt.edu\/OLM\/Courses\/GSP_216_Online\/lesson2-2\/photogrammetry.html<\/a> which confirms those observational requirements. The image above is considered and oblique aerial photography, see <a href=\"http:\/\/gsp.humboldt.edu\/OLM\/Courses\/GSP_216_Online\/lesson2-2\/air-photos.html\">http:\/\/gsp.humboldt.edu\/OLM\/Courses\/GSP_216_Online\/lesson2-2\/air-photos.html<\/a>.<\/p>\n<p>Is it still possible to triangulate the position of the drone from the three points?<\/p>\n<p>We&#8217;ll need to identify what we know and don&#8217;t know. The drone has an unknown elevation, be it above ground or sea level. We don&#8217;t know the heading or bearing of the drone. We can observe the horizon. With a horizon, we can determine the pitch of the drone. We can also use the horizon to calculate the angle from horizon for each point.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/?attachment_id=3603\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3603 size-large\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_HorizonAngles-1024x576.png\" alt=\"\" width=\"640\" height=\"360\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_HorizonAngles-1024x576.png 1024w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_HorizonAngles-300x169.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_HorizonAngles-768x432.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_HorizonAngles-480x270.png 480w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_HorizonAngles.png 1280w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>Drone Pitch = -23.182<br \/>\n1st Base = -20.359<br \/>\n3rd Base = -18.268<br \/>\nSoccer Field = -8.865<\/p>\n<p>This gives us some more detail, but the horizontal angle between each of the points is what we can use to pinpoint where the drone is.<\/p>\n<p>The angle between 3rd base and 1st base can be calculated based on the constant of each pixel = .084375 degrees. The image horizon isn&#8217;t level, so the Pythagorean theorem will need to be used to determine the pixel distance. The selection between each point shows a rectangle of 374 x 48. Here is the process to determine that angle.<\/p>\n<p>374^2 + 48^2 = c^2<br \/>\n139876 + 2304 = 142180<br \/>\n\u221a142180 = 377.067<br \/>\n377.067 * .084375 = 31.815 degrees<\/p>\n<p>The same process will be used to find the horizontal angle between the soccer field and 1st base. However, the selection rectangle is 140 x 2, so it is level enough to do a pixel to degree calculation.<\/p>\n<p>140 * .084375 = 11.8125 degrees<\/p>\n<p>So all of the horizontal angles are<\/p>\n<p>3rd to 1st = 31.815<br \/>\n1st to soccer = 11.8125<br \/>\n3rd to soccer = 43.6275<\/p>\n<p>Plotting these and overlaying them on the Google map should give us the location of the drone. This can be done in GIMP using layers. First I&#8217;ll place the map on a layer. The next layer I&#8217;ll draw a horizontal line and be sure its angle is 0 degrees. I&#8217;ll continue to add lines on this layer starting at the left point of my first line and draw them based on the angle readings above. The second line will have an angle of 11.8125 degrees and the third line will have an angle of 43.6275 degrees. Now I&#8217;ll select the line layer and use the rotate tool to position the converging line point in the general area. I&#8217;ll follow this up with moving the selection so the angle lines line up with the points on the map. I&#8217;ll go back and forth on the rotate and move tools until it starts to line up on all of the points on the map. One of the points was further away so I drew an extension on the line. Now I have the position of the drone when it took the photo, it&#8217;s 47.69610428960238, -122.37881992855307.<\/p>\n<p><a href=\"https:\/\/www.cloudacm.com\/?attachment_id=3604\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-3604 size-large\" src=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Location_Resize-1024x580.png\" alt=\"\" width=\"640\" height=\"363\" srcset=\"https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Location_Resize-1024x580.png 1024w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Location_Resize-300x170.png 300w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Location_Resize-768x435.png 768w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Location_Resize-477x270.png 477w, https:\/\/www.cloudacm.com\/wp-content\/uploads\/2021\/02\/Woody_Location_Resize.png 1156w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>I won&#8217;t go further with this, but I could find the drone heading and bearing. I can also find the elevation of the drone now that I know the distance of the drone from the map points. The speed of the drone could also be determined since the photos were extracted from a video. I would just need to repeat this process on other frames. The differences on location based on time can give me the results.<\/p>\n<p>Although this process is tedious, automating it with computer vision tools along with parallel processing could provide real-time data with live feeds. The manual steps here just give you a glimpse at how it is possible.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>These are a couple of resources that I&#8217;ve used for RC camera information that you may find useful, https:\/\/www.chucklohr.com\/808\/c16\/ and https:\/\/oscarliang.com\/how-to-use-808-16-keychain-camera-manual-and-wiki\/. Those links are specific to the 808-16 key chain camera which I have used for bike rides as well as drone flights. There is mention about field of view measurements in the first link. It references methods used which I was not able to reliably validate. http:\/\/www.rcgroups.com\/forums\/showpost.php?p=22171449&amp;postcount=6843 and https:\/\/www.rcgroups.com\/forums\/showpost.php?p=22446815&amp;postcount=7732 both use the Pythagorean theorem. The camera and background are&#8230;<\/p>\n<p class=\"read-more\"><a class=\"btn btn-default\" href=\"https:\/\/www.cloudacm.com\/?p=3597\"> Read More<span class=\"screen-reader-text\">  Read More<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,3],"tags":[],"class_list":["post-3597","post","type-post","status-publish","format-standard","hentry","category-computer-vision","category-rd"],"_links":{"self":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/3597","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3597"}],"version-history":[{"count":4,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/3597\/revisions"}],"predecessor-version":[{"id":3629,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=\/wp\/v2\/posts\/3597\/revisions\/3629"}],"wp:attachment":[{"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3597"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3597"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.cloudacm.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3597"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}