{"action":"created","comment":{"url":"https://api.github.com/repos/uf-mil/Sub8/pulls/comments/56960122","id":56960122,"diff_hunk":"@@ -1,12 +1,270 @@\n #include <sub8_pcl/cv_tools.hpp>\n \n namespace sub {\n+\n cv::Point contour_centroid(Contour& contour) {\n   cv::Moments m = cv::moments(contour, true);\n   cv::Point center(m.m10 / m.m00, m.m01 / m.m00);\n   return center;\n }\n \n+\n+cv::MatND smooth_histogram(const cv::MatND &histogram, size_t filter_kernel_size, float sigma){\n+\tcv::MatND hist = histogram.clone();\n+\tstd::vector<float> gauss_kernel = generate_gaussian_kernel_1D(filter_kernel_size, sigma);\n+\tsize_t histSize = hist.total();\n+\tsize_t offset = (filter_kernel_size - 1) / 2;\n+\tfor (size_t i = offset; i < histSize-offset; i++ )   // Convolve histogram values with gaussian kernel\n+\t{\n+\t\tint sum = 0;\n+\t\tint kernel_idx = 0;\n+\t\tfor (int j = i - offset; j <= i + offset; j++){\n+\t\t\tsum += (hist.at<float>(j) * gauss_kernel[kernel_idx++]);\n+\t    }\n+\t    hist.at<float>(i) = sum;\n+\t}\n+\tfor (int i = 0; i < offset; ++i)  // Pad filtered result with zeroes\n+\t{\n+\t\thist.at<float>(i) = 0;\n+\t\thist.at<float>(histSize - 1 - i) = 0;\n+\t}\n+\treturn hist;\n+}\n+\n+\n+std::vector<float> generate_gaussian_kernel_1D(size_t kernel_size, float sigma){\n+\tstd::vector<float> kernel;\n+\tint middle_index = (kernel_size - 1) / 2;\n+\tint first_discrete_sample_x = -(middle_index);\n+\tfor (int i = first_discrete_sample_x; i <= 0; i++)\n+\t{\n+\t\tfloat power = -0.5 * (float(i)/sigma) * (float(i)/sigma);\n+\t\tkernel.push_back( exp(power) );\t\t\t\t// From definition of Standard Normal Distribution\n+\t}\n+\tfor(int i = 1; i <= middle_index; i++){\t\t\t// Kernel is symmetric\n+\t\tkernel.push_back(kernel[middle_index - i]);\n+\t}\n+\t// Normalize kernel (sum of values should equal 1.0)\n+\tfloat sum = 0;\n+\tfor (size_t i = 0; i < kernel_size; i++){ sum += kernel[i];\t}\n+\tfor (size_t i = 0; i < kernel_size; i++){ kernel[i] /= sum;\t}\n+\treturn kernel;\n+}\n+\n+\n+std::vector<cv::Point> find_local_maxima(const cv::MatND &histogram, float thresh_multiplier){\n+\tstd::vector<cv::Point> local_maxima, threshed_local_maxima;\n+\tfloat global_maximum = 0;\n+\n+\t// Locate local maxima and find global maximum\n+\tfor(size_t idx = 1; idx < histogram.total() - 1; idx++){\n+\t\tfloat current_value = histogram.at<float>(idx);\n+\t    if((histogram.at<float>(idx-1) < current_value) && (histogram.at<float>(idx+1) <= current_value)){\n+\t    \tlocal_maxima.push_back(cv::Point(idx, current_value));\n+\t    \tif(global_maximum < current_value) global_maximum = current_value;\n+\t    }\n+\t}\n+\t// std::cout << std::endl << \"Maxima: \";\n+\tBOOST_FOREACH(cv::Point pt, local_maxima){\n+\t\tif(pt.y > global_maximum * thresh_multiplier) threshed_local_maxima.push_back(pt);\n+\t\t// std::cout << boost::format(\"[%1%, %2%] \") % pt.x % pt.y;\n+\t}\n+\t// std::cout << std::endl << boost::format(\"thresh: > global_maximum(%1%) * thresh_multiplier(%2%) = %3%\") \n+\t// \t\t\t\t\t\t\t% global_maximum % thresh_multiplier % (global_maximum * thresh_multiplier);\n+\t// std::cout << std::endl << \"Threshed Maxima (x): \";\n+\t// if (threshed_local_maxima.size() != local_maxima.size()){\n+\t// \tBOOST_FOREACH(cv::Point pt, threshed_local_maxima){\n+\t// \t\tstd::cout << boost::format(\" %1% \") % pt.x;\n+\t// \t}\n+\t// }\n+\t// else std::cout << \"same as 'Maxima'\";\n+\t// std::cout << std::endl;\n+\treturn threshed_local_maxima;\n+}\n+\n+\n+std::vector<cv::Point> find_local_minima(const cv::MatND &histogram, float thresh_multiplier){","path":"gnc/sub8_perception/src/sub8_pcl/cv_utils.cc","position":86,"original_position":86,"commit_id":"dc7f70ee67a0d024a97d75d81629d3e40a2f0574","original_commit_id":"dc7f70ee67a0d024a97d75d81629d3e40a2f0574","user":{"login":"jpanikulam","id":6531468,"avatar_url":"https://avatars.githubusercontent.com/u/6531468?v=3","gravatar_id":"","url":"https://api.github.com/users/jpanikulam","html_url":"https://github.com/jpanikulam","followers_url":"https://api.github.com/users/jpanikulam/followers","following_url":"https://api.github.com/users/jpanikulam/following{/other_user}","gists_url":"https://api.github.com/users/jpanikulam/gists{/gist_id}","starred_url":"https://api.github.com/users/jpanikulam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpanikulam/subscriptions","organizations_url":"https://api.github.com/users/jpanikulam/orgs","repos_url":"https://api.github.com/users/jpanikulam/repos","events_url":"https://api.github.com/users/jpanikulam/events{/privacy}","received_events_url":"https://api.github.com/users/jpanikulam/received_events","type":"User","site_admin":false},"body":"Add brief doc -- what exactly does thresh_multiplier do?","created_at":"2016-03-22T09:56:10Z","updated_at":"2016-03-22T09:56:10Z","html_url":"https://github.com/uf-mil/Sub8/pull/68#discussion_r56960122","pull_request_url":"https://api.github.com/repos/uf-mil/Sub8/pulls/68","_links":{"self":{"href":"https://api.github.com/repos/uf-mil/Sub8/pulls/comments/56960122"},"html":{"href":"https://github.com/uf-mil/Sub8/pull/68#discussion_r56960122"},"pull_request":{"href":"https://api.github.com/repos/uf-mil/Sub8/pulls/68"}}},"pull_request":{"url":"https://api.github.com/repos/uf-mil/Sub8/pulls/68","id":63689553,"html_url":"https://github.com/uf-mil/Sub8/pull/68","diff_url":"https://github.com/uf-mil/Sub8/pull/68.diff","patch_url":"https://github.com/uf-mil/Sub8/pull/68.patch","issue_url":"https://api.github.com/repos/uf-mil/Sub8/issues/68","number":68,"state":"open","locked":false,"title":"PERCEPTION: add automatic robust image segmentation","user":{"login":"DSsoto","id":8714358,"avatar_url":"https://avatars.githubusercontent.com/u/8714358?v=3","gravatar_id":"","url":"https://api.github.com/users/DSsoto","html_url":"https://github.com/DSsoto","followers_url":"https://api.github.com/users/DSsoto/followers","following_url":"https://api.github.com/users/DSsoto/following{/other_user}","gists_url":"https://api.github.com/users/DSsoto/gists{/gist_id}","starred_url":"https://api.github.com/users/DSsoto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DSsoto/subscriptions","organizations_url":"https://api.github.com/users/DSsoto/orgs","repos_url":"https://api.github.com/users/DSsoto/repos","events_url":"https://api.github.com/users/DSsoto/events{/privacy}","received_events_url":"https://api.github.com/users/DSsoto/received_events","type":"User","site_admin":false},"body":"This pull request adds robust segmentation capabilities to the sub8_perception package.\r\nIt is designed to segment out foreground objects of solid color whose color distribution does not significantly overlap with that of the background. It tries to find the foreground distribution's mode and calculate ideal threshold values by finding specific zero_crossings of the histogram's derivative. \r\n\r\nThis method makes segmentation of solid colors extremely robust to lighting changes and some color loss, since no hardcoded thresholds are used. In my tests, telling it to look for hue distribution peaks from anywhere from red to green all resulted in successful segmentation of the yellow torpedo board. \r\n\r\nThe following image shows this in action: \r\n![screenshot from 2016-03-22 04 53 48](https://cloud.githubusercontent.com/assets/8714358/13946787/04bb13d6-efed-11e5-81a2-d35d0e89214e.png)\r\n\r\nAssigning to @rleyva  and @jpanikulam for review.\r\n","created_at":"2016-03-22T09:20:45Z","updated_at":"2016-03-22T09:56:10Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0e57b45d4156713a721c9676f75e9601db46ddd7","assignee":{"login":"jpanikulam","id":6531468,"avatar_url":"https://avatars.githubusercontent.com/u/6531468?v=3","gravatar_id":"","url":"https://api.github.com/users/jpanikulam","html_url":"https://github.com/jpanikulam","followers_url":"https://api.github.com/users/jpanikulam/followers","following_url":"https://api.github.com/users/jpanikulam/following{/other_user}","gists_url":"https://api.github.com/users/jpanikulam/gists{/gist_id}","starred_url":"https://api.github.com/users/jpanikulam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpanikulam/subscriptions","organizations_url":"https://api.github.com/users/jpanikulam/orgs","repos_url":"https://api.github.com/users/jpanikulam/repos","events_url":"https://api.github.com/users/jpanikulam/events{/privacy}","received_events_url":"https://api.github.com/users/jpanikulam/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/uf-mil/Sub8/pulls/68/commits","review_comments_url":"https://api.github.com/repos/uf-mil/Sub8/pulls/68/comments","review_comment_url":"https://api.github.com/repos/uf-mil/Sub8/pulls/comments{/number}","comments_url":"https://api.github.com/repos/uf-mil/Sub8/issues/68/comments","statuses_url":"https://api.github.com/repos/uf-mil/Sub8/statuses/dc7f70ee67a0d024a97d75d81629d3e40a2f0574","head":{"label":"DSsoto:torpedo_board","ref":"torpedo_board","sha":"dc7f70ee67a0d024a97d75d81629d3e40a2f0574","user":{"login":"DSsoto","id":8714358,"avatar_url":"https://avatars.githubusercontent.com/u/8714358?v=3","gravatar_id":"","url":"https://api.github.com/users/DSsoto","html_url":"https://github.com/DSsoto","followers_url":"https://api.github.com/users/DSsoto/followers","following_url":"https://api.github.com/users/DSsoto/following{/other_user}","gists_url":"https://api.github.com/users/DSsoto/gists{/gist_id}","starred_url":"https://api.github.com/users/DSsoto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DSsoto/subscriptions","organizations_url":"https://api.github.com/users/DSsoto/orgs","repos_url":"https://api.github.com/users/DSsoto/repos","events_url":"https://api.github.com/users/DSsoto/events{/privacy}","received_events_url":"https://api.github.com/users/DSsoto/received_events","type":"User","site_admin":false},"repo":{"id":46311889,"name":"Sub8","full_name":"DSsoto/Sub8","owner":{"login":"DSsoto","id":8714358,"avatar_url":"https://avatars.githubusercontent.com/u/8714358?v=3","gravatar_id":"","url":"https://api.github.com/users/DSsoto","html_url":"https://github.com/DSsoto","followers_url":"https://api.github.com/users/DSsoto/followers","following_url":"https://api.github.com/users/DSsoto/following{/other_user}","gists_url":"https://api.github.com/users/DSsoto/gists{/gist_id}","starred_url":"https://api.github.com/users/DSsoto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DSsoto/subscriptions","organizations_url":"https://api.github.com/users/DSsoto/orgs","repos_url":"https://api.github.com/users/DSsoto/repos","events_url":"https://api.github.com/users/DSsoto/events{/privacy}","received_events_url":"https://api.github.com/users/DSsoto/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/DSsoto/Sub8","description":"Subjugator 8 On-board software","fork":true,"url":"https://api.github.com/repos/DSsoto/Sub8","forks_url":"https://api.github.com/repos/DSsoto/Sub8/forks","keys_url":"https://api.github.com/repos/DSsoto/Sub8/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DSsoto/Sub8/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DSsoto/Sub8/teams","hooks_url":"https://api.github.com/repos/DSsoto/Sub8/hooks","issue_events_url":"https://api.github.com/repos/DSsoto/Sub8/issues/events{/number}","events_url":"https://api.github.com/repos/DSsoto/Sub8/events","assignees_url":"https://api.github.com/repos/DSsoto/Sub8/assignees{/user}","branches_url":"https://api.github.com/repos/DSsoto/Sub8/branches{/branch}","tags_url":"https://api.github.com/repos/DSsoto/Sub8/tags","blobs_url":"https://api.github.com/repos/DSsoto/Sub8/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DSsoto/Sub8/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DSsoto/Sub8/git/refs{/sha}","trees_url":"https://api.github.com/repos/DSsoto/Sub8/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DSsoto/Sub8/statuses/{sha}","languages_url":"https://api.github.com/repos/DSsoto/Sub8/languages","stargazers_url":"https://api.github.com/repos/DSsoto/Sub8/stargazers","contributors_url":"https://api.github.com/repos/DSsoto/Sub8/contributors","subscribers_url":"https://api.github.com/repos/DSsoto/Sub8/subscribers","subscription_url":"https://api.github.com/repos/DSsoto/Sub8/subscription","commits_url":"https://api.github.com/repos/DSsoto/Sub8/commits{/sha}","git_commits_url":"https://api.github.com/repos/DSsoto/Sub8/git/commits{/sha}","comments_url":"https://api.github.com/repos/DSsoto/Sub8/comments{/number}","issue_comment_url":"https://api.github.com/repos/DSsoto/Sub8/issues/comments{/number}","contents_url":"https://api.github.com/repos/DSsoto/Sub8/contents/{+path}","compare_url":"https://api.github.com/repos/DSsoto/Sub8/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DSsoto/Sub8/merges","archive_url":"https://api.github.com/repos/DSsoto/Sub8/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DSsoto/Sub8/downloads","issues_url":"https://api.github.com/repos/DSsoto/Sub8/issues{/number}","pulls_url":"https://api.github.com/repos/DSsoto/Sub8/pulls{/number}","milestones_url":"https://api.github.com/repos/DSsoto/Sub8/milestones{/number}","notifications_url":"https://api.github.com/repos/DSsoto/Sub8/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DSsoto/Sub8/labels{/name}","releases_url":"https://api.github.com/repos/DSsoto/Sub8/releases{/id}","deployments_url":"https://api.github.com/repos/DSsoto/Sub8/deployments","created_at":"2015-11-17T00:18:40Z","updated_at":"2016-03-07T15:45:26Z","pushed_at":"2016-03-22T09:03:16Z","git_url":"git://github.com/DSsoto/Sub8.git","ssh_url":"git@github.com:DSsoto/Sub8.git","clone_url":"https://github.com/DSsoto/Sub8.git","svn_url":"https://github.com/DSsoto/Sub8","homepage":null,"size":669,"stargazers_count":1,"watchers_count":1,"language":"C++","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"uf-mil:master","ref":"master","sha":"debefcaa172e6b2289118d104eae81e35d4faf1e","user":{"login":"uf-mil","id":6162945,"avatar_url":"https://avatars.githubusercontent.com/u/6162945?v=3","gravatar_id":"","url":"https://api.github.com/users/uf-mil","html_url":"https://github.com/uf-mil","followers_url":"https://api.github.com/users/uf-mil/followers","following_url":"https://api.github.com/users/uf-mil/following{/other_user}","gists_url":"https://api.github.com/users/uf-mil/gists{/gist_id}","starred_url":"https://api.github.com/users/uf-mil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uf-mil/subscriptions","organizations_url":"https://api.github.com/users/uf-mil/orgs","repos_url":"https://api.github.com/users/uf-mil/repos","events_url":"https://api.github.com/users/uf-mil/events{/privacy}","received_events_url":"https://api.github.com/users/uf-mil/received_events","type":"Organization","site_admin":false},"repo":{"id":41452384,"name":"Sub8","full_name":"uf-mil/Sub8","owner":{"login":"uf-mil","id":6162945,"avatar_url":"https://avatars.githubusercontent.com/u/6162945?v=3","gravatar_id":"","url":"https://api.github.com/users/uf-mil","html_url":"https://github.com/uf-mil","followers_url":"https://api.github.com/users/uf-mil/followers","following_url":"https://api.github.com/users/uf-mil/following{/other_user}","gists_url":"https://api.github.com/users/uf-mil/gists{/gist_id}","starred_url":"https://api.github.com/users/uf-mil/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uf-mil/subscriptions","organizations_url":"https://api.github.com/users/uf-mil/orgs","repos_url":"https://api.github.com/users/uf-mil/repos","events_url":"https://api.github.com/users/uf-mil/events{/privacy}","received_events_url":"https://api.github.com/users/uf-mil/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/uf-mil/Sub8","description":"Subjugator 8 On-board software","fork":false,"url":"https://api.github.com/repos/uf-mil/Sub8","forks_url":"https://api.github.com/repos/uf-mil/Sub8/forks","keys_url":"https://api.github.com/repos/uf-mil/Sub8/keys{/key_id}","collaborators_url":"https://api.github.com/repos/uf-mil/Sub8/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/uf-mil/Sub8/teams","hooks_url":"https://api.github.com/repos/uf-mil/Sub8/hooks","issue_events_url":"https://api.github.com/repos/uf-mil/Sub8/issues/events{/number}","events_url":"https://api.github.com/repos/uf-mil/Sub8/events","assignees_url":"https://api.github.com/repos/uf-mil/Sub8/assignees{/user}","branches_url":"https://api.github.com/repos/uf-mil/Sub8/branches{/branch}","tags_url":"https://api.github.com/repos/uf-mil/Sub8/tags","blobs_url":"https://api.github.com/repos/uf-mil/Sub8/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/uf-mil/Sub8/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/uf-mil/Sub8/git/refs{/sha}","trees_url":"https://api.github.com/repos/uf-mil/Sub8/git/trees{/sha}","statuses_url":"https://api.github.com/repos/uf-mil/Sub8/statuses/{sha}","languages_url":"https://api.github.com/repos/uf-mil/Sub8/languages","stargazers_url":"https://api.github.com/repos/uf-mil/Sub8/stargazers","contributors_url":"https://api.github.com/repos/uf-mil/Sub8/contributors","subscribers_url":"https://api.github.com/repos/uf-mil/Sub8/subscribers","subscription_url":"https://api.github.com/repos/uf-mil/Sub8/subscription","commits_url":"https://api.github.com/repos/uf-mil/Sub8/commits{/sha}","git_commits_url":"https://api.github.com/repos/uf-mil/Sub8/git/commits{/sha}","comments_url":"https://api.github.com/repos/uf-mil/Sub8/comments{/number}","issue_comment_url":"https://api.github.com/repos/uf-mil/Sub8/issues/comments{/number}","contents_url":"https://api.github.com/repos/uf-mil/Sub8/contents/{+path}","compare_url":"https://api.github.com/repos/uf-mil/Sub8/compare/{base}...{head}","merges_url":"https://api.github.com/repos/uf-mil/Sub8/merges","archive_url":"https://api.github.com/repos/uf-mil/Sub8/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/uf-mil/Sub8/downloads","issues_url":"https://api.github.com/repos/uf-mil/Sub8/issues{/number}","pulls_url":"https://api.github.com/repos/uf-mil/Sub8/pulls{/number}","milestones_url":"https://api.github.com/repos/uf-mil/Sub8/milestones{/number}","notifications_url":"https://api.github.com/repos/uf-mil/Sub8/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/uf-mil/Sub8/labels{/name}","releases_url":"https://api.github.com/repos/uf-mil/Sub8/releases{/id}","deployments_url":"https://api.github.com/repos/uf-mil/Sub8/deployments","created_at":"2015-08-26T22:11:51Z","updated_at":"2016-03-09T11:55:35Z","pushed_at":"2016-03-22T09:20:45Z","git_url":"git://github.com/uf-mil/Sub8.git","ssh_url":"git@github.com:uf-mil/Sub8.git","clone_url":"https://github.com/uf-mil/Sub8.git","svn_url":"https://github.com/uf-mil/Sub8","homepage":null,"size":697,"stargazers_count":4,"watchers_count":4,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":10,"mirror_url":null,"open_issues_count":7,"forks":10,"open_issues":7,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/uf-mil/Sub8/pulls/68"},"html":{"href":"https://github.com/uf-mil/Sub8/pull/68"},"issue":{"href":"https://api.github.com/repos/uf-mil/Sub8/issues/68"},"comments":{"href":"https://api.github.com/repos/uf-mil/Sub8/issues/68/comments"},"review_comments":{"href":"https://api.github.com/repos/uf-mil/Sub8/pulls/68/comments"},"review_comment":{"href":"https://api.github.com/repos/uf-mil/Sub8/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/uf-mil/Sub8/pulls/68/commits"},"statuses":{"href":"https://api.github.com/repos/uf-mil/Sub8/statuses/dc7f70ee67a0d024a97d75d81629d3e40a2f0574"}}}}