{"id":1966,"date":"2011-12-12T20:19:46","date_gmt":"2011-12-13T03:19:46","guid":{"rendered":"http:\/\/mcclanahoochie.com\/blog\/?post_type=portfolio&#038;p=1966"},"modified":"2023-06-10T10:32:42","modified_gmt":"2023-06-10T17:32:42","slug":"computer-vision-learning-portfolio","status":"publish","type":"post","link":"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/","title":{"rendered":"Computer Vision Learning Portfolio"},"content":{"rendered":"<p>This page constitutes my required\u00a0<em>external<\/em>\u00a0learning portfolio for<a href=\"http:\/\/web.me.com\/dellaert\/11F-7495\/\" target=\"_blank\" rel=\"noopener\"> CS 7495,<\/a> Computer Vision, taken in Fall 2011. In it, I discuss what I have learned throughout the course, my activities and findings, how I think I did, and what impact it had on me.<\/p>\n<h1>About me<\/h1>\n<p><a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/chris-raffertys-2.jpg\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1967\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/chris-raffertys-2\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/chris-raffertys-2.jpg?fit=400%2C400&amp;ssl=1\" data-orig-size=\"400,400\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;2.8&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;iPhone 4&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;1314383546&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;3.85&quot;,&quot;iso&quot;:&quot;200&quot;,&quot;shutter_speed&quot;:&quot;0.0666666666667&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"chris-raffertys-2\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/chris-raffertys-2.jpg?fit=400%2C400&amp;ssl=1\" class=\"aligncenter size-thumbnail wp-image-1967\" title=\"chris-raffertys-2\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/chris-raffertys-2-150x150.jpg?resize=150%2C150\" alt=\"\" width=\"150\" height=\"150\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/chris-raffertys-2.jpg?resize=150%2C150&amp;ssl=1 150w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/chris-raffertys-2.jpg?resize=300%2C300&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/chris-raffertys-2.jpg?w=400&amp;ssl=1 400w\" sizes=\"(max-width: 150px) 100vw, 150px\" \/><\/a><\/p>\n<p>I am a coffee fanatic that is into computers, photography, computer vision, computational photography, and electronics. I am currently working toward a Master\u2019s Degree in Computer Science at Georgia Tech. My passion is in using GPUs for computer vision, and I\u2019m also a part-time software engineer at <a href=\"http:\/\/accelereyes.com\/\" target=\"_blank\" rel=\"noopener\">AccelerEyes<\/a> (the people who make <a href=\"http:\/\/www.accelereyes.com\/\" target=\"_blank\" rel=\"noopener\">Jacket<\/a>: the GPU plug-in for Matlab).<\/p>\n<p>Foundation: Reading and Assignments<\/p>\n<p>In the course, we completed several assignments on the foundations of computer vision, after reading the relevant material in the textbook.<\/p>\n<ul>\n<li>The homework assignments covered topics in geometry, signal-processing, multiple images, segmentation, tracking, and object detection. Different algorithms were covered in each one, such as least-squares fitting, convolution filters, disparity and depth, graphcuts, kalman filtering, and support vector machines.<\/li>\n<li>My favorite assignment was the one covering SVMs. After this assignment, I had a better understanding of how support vector machines worked, and for what applications SVMs are useful for.<\/li>\n<\/ul>\n<h1>Skills: Mini-projects<\/h1>\n<p>There were three mini-projects in which I chose to research a problem that was supposed to be relevant to my future career. For each of these three projects, I proposed a solution, implemented it, and described it in a mini-conference paper.<br \/>\n(collaborator: <a href=\"http:\/\/www.cc.gatech.edu\/grads\/b\/bhroleno\/\" target=\"_blank\" rel=\"noopener\">Brian Hrolenok<\/a>)<\/p>\n<h3><span style=\"text-decoration: underline;\"><span style=\"color: #333333;\"><em>Project 1: Measuring Feature Stability in Video<\/em><\/span><\/span><\/h3>\n<p><a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/sparse-ants.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1968\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/sparse-ants\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/sparse-ants.png?fit=298%2C223&amp;ssl=1\" data-orig-size=\"298,223\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"sparse-ants\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/sparse-ants.png?fit=298%2C223&amp;ssl=1\" class=\"size-thumbnail wp-image-1968 alignnone\" title=\"sparse-ants\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/sparse-ants-150x150.png?resize=150%2C150\" alt=\"\" width=\"150\" height=\"150\" \/><\/a><a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/per-feat-corr-bees.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1969\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/per-feat-corr-bees\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/per-feat-corr-bees.png?fit=833%2C641&amp;ssl=1\" data-orig-size=\"833,641\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"per-feat-corr-bees\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/per-feat-corr-bees.png?fit=833%2C641&amp;ssl=1\" class=\"size-thumbnail wp-image-1969 alignnone\" title=\"per-feat-corr-bees\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/per-feat-corr-bees-150x150.png?resize=150%2C150\" alt=\"\" width=\"150\" height=\"150\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/per-feat-corr-bees.png?resize=150%2C150&amp;ssl=1 150w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/per-feat-corr-bees.png?zoom=2&amp;resize=150%2C150&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/per-feat-corr-bees.png?zoom=3&amp;resize=150%2C150&amp;ssl=1 450w\" sizes=\"(max-width: 150px) 100vw, 150px\" \/><\/a><\/p>\n<p>Our purpose in this project was to propose and evaluate a set of metrics for comparing various combinations of OpenCV&#8217;s feature <a href=\"http:\/\/opencv.itseez.com\/doc\/tutorials\/features2d\/table_of_content_features2d\/table_of_content_features2d.html#table-of-content-feature2d\" target=\"_blank\" rel=\"noopener\">descriptors\/detectors<\/a> pairs on domain specific video (ants and bees). Of the metrics used, the one in which most clearly illustrates feature performance is the percentage of correctly tracked features. We learned that examining the frequency of incorrect assignments is more useful than the level of incorrectness when comparing these feature detectors\/descriptors, and also that the choice of detector has more of an impact on performance than the choice of descriptor. We saw in our tests that the SURF detector consistently ranked well on each metric, making it the most robust detector we tested. We also got a nice intuition about how each detector and descriptor works under the hood while watching them all in a controlled manner.<\/p>\n<h3><span style=\"text-decoration: underline;\"><span style=\"color: #333333;\"><em>Project 2: GPU TV-L1 Optical Flow<\/em><\/span><\/span><\/h3>\n<p><a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/oflow-face.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1972\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/oflow-face\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/oflow-face.png?fit=663%2C273&amp;ssl=1\" data-orig-size=\"663,273\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"oflow-face\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/oflow-face.png?fit=663%2C273&amp;ssl=1\" class=\"size-medium wp-image-1972 alignnone\" title=\"oflow-face\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/oflow-face-300x123.png?resize=300%2C123\" alt=\"\" width=\"300\" height=\"123\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/oflow-face.png?resize=300%2C123&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/oflow-face.png?resize=500%2C205&amp;ssl=1 500w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/oflow-face.png?w=663&amp;ssl=1 663w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p>In this project, we implement and compare two different optical flow algorithms on the GPU using OpenCL: <a href=\"http:\/\/en.wikipedia.org\/wiki\/Horn%E2%80%93Schunck_method\" target=\"_blank\" rel=\"noopener\">Horn-Schunck<\/a> and <a href=\"http:\/\/r.search.yahoo.com\/_ylt=A0SO8wHzA15XezIAandXNyoA;_ylu=X3oDMTEyOHIyOWlkBGNvbG8DZ3ExBHBvcwMxBHZ0aWQDQjA3NzNfMQRzZWMDc3I-\/RV=2\/RE=1465807987\/RO=10\/RU=https%3a%2f%2fvision.in.tum.de%2f_media%2fspezial%2fbib%2fdagstuhlopticalflowchapter.pdf\/RK=0\/RS=vDm2KQr3x4svBEsQfUDJzy_uFRo-\" target=\"_blank\" rel=\"noopener\">TV-L1<\/a> (L1 norm Total Variation) optical flow. The Horn-Schunck method is relatively simple and fast, but produces larger single pixel error and cannot capture large motions very well. For TV-L1, flow is computed on coarse sub-sampled images with and optimization formulation of the problem, and then propagated as an initial estimate for the next pyramid level for iterative solving. Increasing the number of pyramid levels is more performance costly than increasing the number of inner iterations, as pyramids involve more memory transfer overhead. While the alternative formulation of the L1-optimization problem leads to a more robust solution, probably the most important improvements the TV-L1 approach has over standard Horn-Schunck are the inclusion of an image pyramid to handle larger scale motion, and the median filter to remove outliers.<\/p>\n<h3><span style=\"text-decoration: underline;\"><span style=\"color: #333333;\"><em>Project 3: HOG Features on the GPU<\/em><\/span><\/span><\/h3>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1970\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/1-hog-mag\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hog-mag.png?fit=635%2C500&amp;ssl=1\" data-orig-size=\"635,500\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"1-hog-mag\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hog-mag.png?fit=635%2C500&amp;ssl=1\" class=\"size-thumbnail wp-image-1970 alignnone\" title=\"1-hog-mag\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hog-mag-150x150.png?resize=150%2C150\" alt=\"\" width=\"150\" height=\"150\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hog-mag.png?resize=150%2C150&amp;ssl=1 150w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hog-mag.png?zoom=2&amp;resize=150%2C150&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hog-mag.png?zoom=3&amp;resize=150%2C150&amp;ssl=1 450w\" sizes=\"(max-width: 150px) 100vw, 150px\" \/><a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-hog-ori.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1971\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/2-hog-ori\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-hog-ori.png?fit=632%2C500&amp;ssl=1\" data-orig-size=\"632,500\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"2-hog-ori\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-hog-ori.png?fit=632%2C500&amp;ssl=1\" class=\"size-thumbnail wp-image-1971 alignnone\" title=\"2-hog-ori\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-hog-ori-150x150.png?resize=150%2C150\" alt=\"\" width=\"150\" height=\"150\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-hog-ori.png?resize=150%2C150&amp;ssl=1 150w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-hog-ori.png?zoom=2&amp;resize=150%2C150&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-hog-ori.png?zoom=3&amp;resize=150%2C150&amp;ssl=1 450w\" sizes=\"(max-width: 150px) 100vw, 150px\" \/><\/a><\/p>\n<p>Our original premise for this project was that we could efficiently compute <a href=\"http:\/\/en.wikipedia.org\/wiki\/Histogram_of_oriented_gradients\" target=\"_blank\" rel=\"noopener\">HOG features<\/a> using the GPU, and that using HOG features would improve classification performance. Unfortunately we were only able to show the former in this project. Our implementation of HOG feature descriptor runs in real time: 0.06 seconds to compute a HOG feature with 16 \u00d7 16 cells and 8 bins per histogram for a 640 \u00d7 480 frame on a consumer laptop. Our naive sliding window approach for classification was quite simple, but slower than we had hoped. Although we made a few attempts, in the given time frame we were unable to get the SVM to train properly on our limited dataset for detecting faces. A neat visualization was made for showing in real-time each cell&#8217;s dominant histogram orientation (the canonical HOG display) on a live webcam input.<br \/>\n<strong><em><a href=\"https:\/\/code.google.com\/p\/mcclanahoochie\/source\/browse\/#git\/opencl\/hog_features\" target=\"_blank\" rel=\"noopener\">Open Source!<\/a><\/em><\/strong><br \/>\n<strong> <em><a href=\"http:\/\/www.youtube.com\/watch?v=N-BMttqI_oc\" target=\"_blank\" rel=\"noopener\">Demo Video!<\/a><\/em><\/strong><\/p>\n<h3><em>How we did:<\/em><\/h3>\n<p>Overall, each project presented us with unique challenges and opportunities to learn from. I feel my group and I performed well on every project &#8211; especially given the time constraints and that all of us had multiple other classes with other projects due. The most important lesson to learn about these projects was how to effectively plan and manage the given time period to complete the project. The first project was originally a &#8220;warm up&#8221;, but turned out to be quite involved and interesting. Of the three, the second project was by far the coolest paper to implement and demo. The last project was also fun and had an impressive demo to show (even though we didn&#8217;t get the extra step working).<\/p>\n<h3><em>Links to project papers:<\/em><\/h3>\n<ul>\n<li><a href=\"http:\/\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/paper1.pdf\">paper1<\/a>\u00a0&#8211; Measuring Feature Stability in Video<\/li>\n<li><a href=\"http:\/\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/paper2.pdf\">paper2<\/a>\u00a0&#8211; GPU TV-L1 Optical Flow<\/li>\n<li><a href=\"http:\/\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/paper3.pdf\">paper3<\/a>\u00a0&#8211; HOG Features on the GPU<\/li>\n<\/ul>\n<h1>My favorite Project: GPU TV-L1 Optical Flow<\/h1>\n<p><a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/garden-tvl1.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1973\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/garden-tvl1\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/garden-tvl1.png?fit=539%2C200&amp;ssl=1\" data-orig-size=\"539,200\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"garden-tvl1\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/garden-tvl1.png?fit=539%2C200&amp;ssl=1\" class=\"size-medium wp-image-1973 alignnone\" title=\"garden-tvl1\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/garden-tvl1-300x111.png?resize=300%2C111\" alt=\"\" width=\"300\" height=\"111\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/garden-tvl1.png?resize=300%2C111&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/garden-tvl1.png?resize=500%2C185&amp;ssl=1 500w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/garden-tvl1.png?w=539&amp;ssl=1 539w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h3><em>Problem<\/em><\/h3>\n<p>Determining optical flow, the pattern of apparent motion of objects caused by the relative motion between observer and objects in the scene, is a fundamental problem in computer vision. Given two images, goal is to compute the 2D motion field &#8211; a projection of 3D velocities of surface points onto the imaging surface. Optical flow can be used in a wide range of higher level computer vision tasks, from object tracking and robot navigation to motion estimation and image stabilization.<\/p>\n<p>There is a real need for shortening the required computational time of optical flow for use in practical applications such as robotics motion analysis and security systems. With the advances in utilizing GPUs for general computation, it\u2019s become feasible to use more accurate (but computationally expensive) optical flow algorithms for these practical applications.<\/p>\n<p>With that in mind, we propose to implement an improved L1-norm based total-variation optical flow (TV-L1) on the GPU.<\/p>\n<h3><em>Related Works<\/em><\/h3>\n<p>Graphical Processing Units (GPUs) were originally developed for fast rendering in computer graphics, but recently high level languages such as CUDA and OpenCL have enabled general-purpose GPU computation (<a href=\"http:\/\/gpgpu.org\/\" target=\"_blank\" rel=\"noopener\">GPGPU<\/a>). This is useful In the field of computer vision and pattern recognition, and <a href=\"http:\/\/ieeexplore.ieee.org\/xpl\/freeabs_all.jsp?arnumber=4362776\" target=\"_blank\" rel=\"noopener\">Mizukami2007<\/a> demonstrate this by implementing the Horn-Schunck method on GPUs using OpenCL.<\/p>\n<p>Two well known variational approaches to computing the optical flow are the point based method, presented in Horn and Schunck (<a href=\"http:\/\/www.sciencedirect.com\/science\/article\/pii\/0004370281900242\" target=\"_blank\" rel=\"noopener\">Horn1981<\/a>), and the local patch based method of Lucas and Kanade <a href=\"http:\/\/dl.acm.org\/citation.cfm?id=1623280\" target=\"_blank\" rel=\"noopener\">Lucas1981<\/a>. Our approach is an improvement of <a href=\"http:\/\/www.sciencedirect.com\/science\/article\/pii\/0004370281900242\" target=\"_blank\" rel=\"noopener\">Horn1981<\/a>\u00a0that replaces the squared measure of error with an L1 norm. The highly data-parallel nature of the solution lends itself well to a GPU implementation.<\/p>\n<h3><em>Approach<\/em><\/h3>\n<p>The standard Horn-Schunck algorithm minimizes the following energy equation <a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hs-eq.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1977\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/1-hs-eq\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hs-eq.png?fit=327%2C57&amp;ssl=1\" data-orig-size=\"327,57\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"1-hs-eq\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hs-eq.png?fit=327%2C57&amp;ssl=1\" class=\"aligncenter size-medium wp-image-1977\" title=\"1-hs-eq\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hs-eq-300x52.png?resize=300%2C52\" alt=\"\" width=\"300\" height=\"52\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hs-eq.png?resize=300%2C52&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-hs-eq.png?w=327&amp;ssl=1 327w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>\u00a0where the first integral is known as the regularization term, and the second as the data term. An iterative solution to the above optimization problem is given two equations in terms of the flow field <em>u = (ux,uy)<\/em>, a weighted local average of the flow <em>u`<\/em>, gradient images\u00a0<em>Ix<\/em>, <em>Iy<\/em>, and <em>It<\/em> in <em>x<\/em>, <em>y<\/em> and <em>t<\/em> respectively, and and <em>alpha<\/em> a small constant close to zero. These two equations come from solving the Lagrangian optimization equations associated with the energy function, and using a finite differences approximation of the Laplacian of the flow.<\/p>\n<p>The TV-L1 approach optimizes the following equation\u00a0<a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tvl1-eq.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1978\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/2-tvl1-eq\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tvl1-eq.png?fit=363%2C54&amp;ssl=1\" data-orig-size=\"363,54\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"2-tvl1-eq\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tvl1-eq.png?fit=363%2C54&amp;ssl=1\" class=\"aligncenter size-medium wp-image-1978\" title=\"2-tvl1-eq\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tvl1-eq-300x44.png?resize=300%2C44\" alt=\"\" width=\"300\" height=\"44\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tvl1-eq.png?resize=300%2C44&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tvl1-eq.png?w=363&amp;ssl=1 363w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>which replaces the squared error term with an L1 norm. Wedel et al. propose an iterative solution that alternatively updates the flow and an auxiliary variable v<a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/3-tvl1-eq.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1979\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/3-tvl1-eq\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/3-tvl1-eq.png?fit=411%2C79&amp;ssl=1\" data-orig-size=\"411,79\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"3-tvl1-eq\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/3-tvl1-eq.png?fit=411%2C79&amp;ssl=1\" class=\"aligncenter size-medium wp-image-1979\" title=\"3-tvl1-eq\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/3-tvl1-eq-300x57.png?resize=300%2C57\" alt=\"\" width=\"300\" height=\"57\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/3-tvl1-eq.png?resize=300%2C57&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/3-tvl1-eq.png?w=411&amp;ssl=1 411w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>Where <a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/4-tvl1-eq.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1980\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/4-tvl1-eq\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/4-tvl1-eq.png?fit=296%2C20&amp;ssl=1\" data-orig-size=\"296,20\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"4-tvl1-eq\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/4-tvl1-eq.png?fit=296%2C20&amp;ssl=1\" class=\"aligncenter size-full wp-image-1980\" title=\"4-tvl1-eq\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/4-tvl1-eq.png?resize=296%2C20\" alt=\"\" width=\"296\" height=\"20\" \/><\/a>\u00a0is the current residual. On top of this alternative optimization, we implement a median filter on the flow field, and use image pyramids in a coarse-to-fine approach in order to handle larger scale motions. That is, flow is computed on coarse sub-sampled images, and then propagated as an initial estimate for the next pyramid level.<\/p>\n<p>In both algorithms, there are several points at which an iterative solution for the flow vector of an individual pixel in the image can be computed concurrently with its neighbors. This allows us to improve performance from a serial implementation by using <a href=\"http:\/\/www.khronos.org\/opencl\/\" target=\"_blank\" rel=\"noopener\">OpenCL<\/a>. In particular, we wrote OpenCL kernels to compute flow updates, image gradients, and local flow averages for Horn-Schunck, as well as kernels for u and v updates, and discrete forward and backward differences.<\/p>\n<p>Side note: The first version of the TVL1 code from Matlab to C++ was ported with <del>LibJacket\u00a0<\/del><a href=\"http:\/\/www.accelereyes.com\/arrayfire_cuda\/\" target=\"_blank\" rel=\"noopener\">ArrayFire<\/a>, a high-level, Matlab-like, GPU matrix library. Porting code from Matlab to LibJacket was almost 1-to-1 easy. Good performance is obtained almost out-of-the-box\u00a0using LibJacket, vs writing from scratch OpenCL\/CUDA kernels for TV-L1.<\/p>\n<h3><em>Results<\/em><\/h3>\n<p>We ran both the Horn-Schunck and TV-L1 algorithms on a subset of the <a href=\"http:\/\/vision.middlebury.edu\/flow\/\" target=\"_blank\" rel=\"noopener\">Middlebury<\/a> dataset. We compute and list average and maximum endpoint error in pixels for both algorithms for each dataset. For this table, we ran Horn-Schunck for 60 iterations. More than 60 iterations showed minimal improvement. TV-L1 ran for 7 fixed point iterations, and used a pyramid of 7 images with a 0.9 scaling factor. The figures below illustrate the effect of the number of fixed point iterations and the size of the image pyramid used.<\/p>\n<figure id=\"attachment_1974\" aria-describedby=\"caption-attachment-1974\" style=\"width: 290px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-tv-urban2.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1974\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/1-tv-urban2\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-tv-urban2.png?fit=372%2C140&amp;ssl=1\" data-orig-size=\"372,140\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"1-tv-urban2\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-tv-urban2.png?fit=372%2C140&amp;ssl=1\" class=\"size-medium wp-image-1974\" title=\"1-tv-urban2\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-tv-urban2-300x112.png?resize=300%2C112\" alt=\"\" width=\"300\" height=\"112\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-tv-urban2.png?resize=300%2C112&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/1-tv-urban2.png?w=372&amp;ssl=1 372w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><figcaption id=\"caption-attachment-1974\" class=\"wp-caption-text\">Original, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0Ground Truth<\/figcaption><\/figure>\n<p><a href=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tv-urban2.png\"><img data-recalc-dims=\"1\" decoding=\"async\" data-attachment-id=\"1975\" data-permalink=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/2-tv-urban2\/#main\" data-orig-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tv-urban2.png?fit=564%2C140&amp;ssl=1\" data-orig-size=\"564,140\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}\" data-image-title=\"2-tv-urban2\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tv-urban2.png?fit=564%2C140&amp;ssl=1\" class=\"size-medium wp-image-1975 \" title=\"2-tv-urban2\" src=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tv-urban2-300x74.png?resize=400%2C100\" alt=\"\" width=\"400\" height=\"100\" srcset=\"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tv-urban2.png?resize=300%2C74&amp;ssl=1 300w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tv-urban2.png?resize=500%2C124&amp;ssl=1 500w, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/12\/2-tv-urban2.png?w=564&amp;ssl=1 564w\" sizes=\"(max-width: 400px) 100vw, 400px\" \/><\/a><\/p>\n<p style=\"text-align: left;\">TV-L1 performs better than Horn-Schunck in almost all cases. The difference between the two methods is most clearly seen on the Urban2 setting, which has the largest apparent motion of the group. Since TV-L1 makes use of an image pyramid, we are able to capture larger motion, so this make sense. Our testing also shows that the Horn-Schunck method produces larger single pixel error, which makes sense because the TV-L1 method applies a median filter, and can throw out such outliers.<\/p>\n<p>The parameters used in our tests give roughly the same number of iterations to each method: Horn-Schunck uses a fixed 60 iterations, and TV-L1 performs 7 fixed point iterations at each of 7 pyramid levels. By altering the ratio of fixed point iterations to pyramid levels, the performance of the algorithm on a particular dataset changes, given the same &#8220;budget&#8221; of iterations. By increasing the number of pyramid levels the algorithm can capture larger motions, while increasing fixed point iterations improves the flow estimates at each pyramid level. The figures above show this accuracy trade off. Performance wise, increasing the number of pyramid levels is more costly than increasing the number of inner iterations, as pyramids involve more memory transfer overhead.<\/p>\n<h3><em>What we learned<\/em><\/h3>\n<p>Looking back at the entire project, one important lesson learned is that while the alternative formulation of the optimization problem leads to a more robust solution, probably the most important improvements the TV-L1 approach has over standard Horn-Schunck are the inclusion of an image pyramid to handle larger scale motion, and the median filter to remove outliers.<\/p>\n<p>The purpose of implementing these algorithms on the GPU was to achieve some performance gain over the standard serial version. Our first naive implementation of both TV-L1 and Horn-Schunck algorithms made use of global memory for all computations, which could certainly be improved in future work. An obvious future work item would be to optimize the naive OpenCL kernels and make use of shared\/texture memory.<\/p>\n<p>Our current implementation approaches real-time, running the Venus image at the settings mentioned previously at ~3fps. Additionally, we developed a separate implementation of TV-L1 using the LibJacket library \u2014 a high-level, Matlab-like, GPU matrix library \u2014 which improved the running time over a serial CPU implementation by orders of magnitude, and indeed nears real-time performance.<\/p>\n<h3><em>Why this was my favorite<\/em><\/h3>\n<p>So much new cool stuff on a topic I find interesting: learned a lot about how optical flow works, wrote my first program in OpenCL, first time implementing and using image pyramids, actually produced a &#8216;fast&#8217; GPU optical flow demo&#8230;<\/p>\n<h1>Self-assessment<\/h1>\n<p>Going into each project was pretty much, &#8220;Hey, I have heard of this topic before, and I would like to know more, let&#8217;s try to do\/implement X&#8221;, not knowing in the slightest how to actually do X. &lt;extreme time-limited focus ensues&gt;. Then comes paper review day (when each project is due), and have since dived deep into the selected project topic literature, implmeneted it, written about it, and have a neat demo ready to show off on presentation day. Every project taught me at least a few new things. After Project 1, I know which feature descriptor\/detector pair in OpenCV is best suited for which tasks. After Project 2, I know how to program OpenCL, and have a better understanding and one of the top performing optical flow methods, running on the GPU. After Project 3, I have more OpenCL experience and have a deep understanding and real-time GPU implementation of the HOG feature descriptor. Getting to choose interesting topics made the projects fly by (hmm, or was it the ~2 week deadlines?).<\/p>\n<p>I feel the most proud about the second project, mainly because we had a cool demo (GPU optical flow on my laptop), and I had never used OpenCL before and got to learn it fast and put it to good use. The first project was more of a warm-up, but still interesting and useful to know nonetheless. While we didn&#8217;t propose it, he last project would have been better if we could have gotten the SVM trained properly for face detection, for an even more impressive demo. All projects took a lot of focused effort in a small amount of time. Overall, I got quite a lot out of this course &#8211; from learning about topics from top professors in that field at GaTech, to getting intense hands-on project action on interesting topics.<\/p>\n<h1>Comments for the Instructors<\/h1>\n<p><em>What I particularly liked about the course:<\/em><br \/>\nI enjoyed the free-from, involved projects; having the flexibility to choose topics related to computer vision helped each group do their own thing they find interesting.<\/p>\n<h1>Final Comments<\/h1>\n<p>I&#8217;m glad that I signed up for this course. Even though most of the topics covered were not completely new to me, any gaps in the literature I had on any subject discussed were filled in, and I gained further insight and perspective into topics I was already familiar with.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This page constitutes my required\u00a0external\u00a0learning portfolio for CS 7495, Computer Vision, taken in Fall 2011. In it, I discuss what I have learned throughout the course, my activities and findings, how I think I did, and what impact it had on me. About me I am a coffee fanatic that is into computers, photography, computer &#8230; <a title=\"Computer Vision Learning Portfolio\" class=\"read-more\" href=\"https:\/\/mcclanahoochie.com\/blog\/2011\/12\/computer-vision-learning-portfolio\/\" aria-label=\"Read more about Computer Vision Learning Portfolio\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"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":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[113,54,101,29],"class_list":["post-1966","post","type-post","status-publish","format-standard","hentry","category-uncategorized","tag-computer-vision","tag-image-processing","tag-programming","tag-projects"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/pZdXI-vI","jetpack-related-posts":[{"id":1153,"url":"https:\/\/mcclanahoochie.com\/blog\/2011\/04\/computer-vision-on-android-opencv\/","url_meta":{"origin":1966,"position":0},"title":"Computer Vision on Android with OpenCV","author":"mcclanahoochie","date":"April 8, 2011","format":false,"excerpt":"March 2011 With the help of Motodev Studio for Android, I've\u00a0extracted\u00a0the\u00a0android-opencv JNI\u00a0camera example and spawned a fork of my original computer vision app,\u00a0Viewer, to an OpenCV version: ViewerCV. Both are\u00a0available on Git Hub\u00a0as open source software example of doing Computer Vision on Android with OpenCV. Viewer Features: *FAST Features (default\u2026","rel":"","context":"In \"android\"","block_context":{"text":"android","link":"https:\/\/mcclanahoochie.com\/blog\/tag\/android\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/04\/viewercv1.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":950,"url":"https:\/\/mcclanahoochie.com\/blog\/2011\/01\/computer-vision-on-android\/","url_meta":{"origin":1966,"position":1},"title":"Computer Vision on Android in Java","author":"mcclanahoochie","date":"January 4, 2011","format":false,"excerpt":"January 2010 \u00a0 Over the holiday break, I finally created an Android\u00a0app that allows image processing on the camera's raw data, and displays it back on the screen. It only uses\u00a0Java on the CPU for now, but in my free time I'll be porting the code to OpenGL ES to\u2026","rel":"","context":"In \"android\"","block_context":{"text":"android","link":"https:\/\/mcclanahoochie.com\/blog\/tag\/android\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/01\/device-sobel-2-small.png?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1731,"url":"https:\/\/mcclanahoochie.com\/blog\/2011\/08\/image-processing-with-libjacket-opencv\/","url_meta":{"origin":1966,"position":2},"title":"Image processing with LibJacket + OpenCV","author":"mcclanahoochie","date":"August 24, 2011","format":false,"excerpt":"Update: one year later:\u00a0ArrayFire+OpenCV The OpenCV library is the de-facto standard for doing computer vision and image processing research projects. OpenCV includes several hundreds of computer vision algorithms, aimed for use in real-time vision applications. LibJacket is a matrix library built on CUDA. LibJacket offers hundreds of general matrix and\u2026","rel":"","context":"In \"arrayfire\"","block_context":{"text":"arrayfire","link":"https:\/\/mcclanahoochie.com\/blog\/tag\/arrayfire\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/08\/Screen-shot-2011-08-24-at-2.42.52-PM-1024x640.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/08\/Screen-shot-2011-08-24-at-2.42.52-PM-1024x640.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/08\/Screen-shot-2011-08-24-at-2.42.52-PM-1024x640.png?resize=525%2C300 1.5x"},"classes":[]},{"id":875,"url":"https:\/\/mcclanahoochie.com\/blog\/2011\/01\/igvc-robot\/","url_meta":{"origin":1966,"position":3},"title":"IGVC Robot","author":"mcclanahoochie","date":"January 1, 2011","format":false,"excerpt":"July 2009 I competed in the 2009\u00a0Intelligent Ground Vehicle\u00a0Competition, on the Georgia Tech\u00a0RoboJackets Team.\u00a0Our robot: Candi. I developed the computer vision algorithms to navigate an autonomous vehicle using only a vision camera. Our team ranked\u00a06th place nationwide.\u00a0Competition photos\u00a0here. I wrote all of the vision and mapping code! The robot navigated\u2026","rel":"","context":"In \"competition\"","block_context":{"text":"competition","link":"https:\/\/mcclanahoochie.com\/blog\/tag\/competition\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/01\/igvcbanner.jpg?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":1201,"url":"https:\/\/mcclanahoochie.com\/blog\/2011\/05\/ai-learning-portfolio\/","url_meta":{"origin":1966,"position":4},"title":"AI Learning Portfolio","author":"mcclanahoochie","date":"May 4, 2011","format":false,"excerpt":"As a final assignment\/write-up for my CS6601 Artificial Intelligence class at Georgia Tech, this\u00a0learning portfolio was made to summarize what I had learned throughout the course... CS 6601 Learning Portfolio This page constitutes my learning portfolio for CS 6601, Artificial Intelligence, taken in Spring 2011. In it, I discuss what\u2026","rel":"","context":"In \"ai\"","block_context":{"text":"ai","link":"https:\/\/mcclanahoochie.com\/blog\/tag\/ai\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/05\/Chris2-d%2B_copy_-1.jpg?resize=350%2C200","width":350,"height":200},"classes":[]},{"id":874,"url":"https:\/\/mcclanahoochie.com\/blog\/2011\/01\/laser-projection-vision-system\/","url_meta":{"origin":1966,"position":5},"title":"Laser Projection Vision System","author":"mcclanahoochie","date":"January 1, 2011","format":false,"excerpt":"September 2008 A project at GTRI\u00a0FPTD I worked on\u00a0involving combining a color vision system with a 2D laser projector. Case Study about the project here: \u00a0Using Lasers to Identify Substandard Food. With\u00a0Python and OpenCV,\u00a0I got the system to find contours with the camera, and tell the laser to draw\u00a0them in\u2026","rel":"","context":"In \"computer vision\"","block_context":{"text":"computer vision","link":"https:\/\/mcclanahoochie.com\/blog\/tag\/computer-vision\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/mcclanahoochie.com\/blog\/wp-content\/uploads\/2011\/01\/laser_contours2.png?resize=350%2C200","width":350,"height":200},"classes":[]}],"jetpack_likes_enabled":false,"_links":{"self":[{"href":"https:\/\/mcclanahoochie.com\/blog\/wp-json\/wp\/v2\/posts\/1966","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mcclanahoochie.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mcclanahoochie.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mcclanahoochie.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mcclanahoochie.com\/blog\/wp-json\/wp\/v2\/comments?post=1966"}],"version-history":[{"count":0,"href":"https:\/\/mcclanahoochie.com\/blog\/wp-json\/wp\/v2\/posts\/1966\/revisions"}],"wp:attachment":[{"href":"https:\/\/mcclanahoochie.com\/blog\/wp-json\/wp\/v2\/media?parent=1966"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mcclanahoochie.com\/blog\/wp-json\/wp\/v2\/categories?post=1966"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mcclanahoochie.com\/blog\/wp-json\/wp\/v2\/tags?post=1966"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}