Refining the Hough Transform with Camshift circular Hough Transform-is-often-not very accurate-to due Ails\occlusions.
Typical ways of dealing with this are:
1. Hand tuning the Hough Transform parameters.
2. pre-processing the image aggressively before the transform is applied.
One trick I use to fix the "circles positions is a iterative search in Windows around" initial circles, I hope to have A future post about this.
But now I'll share a much simpler strategy so works, some cases:use camshift to track the circular object in a Window around the initial circles positions.
The idea is this initial Circle center position area holds information about how the circular object looks like, for E Xample its color distribution. This is complementary to the Hough transform which uses only spatial information (the binary votes in the Hough spaces).
The steps:find circles with the circular Hough Transform. Find the histogram inside a small box around each circle. In a I can use any kind of features "we", like texture features or something, but we'll stick With a color features. For each pixel, find the probability it belongs to the circular object (back-projection). Optional:apply some strategy to fill holes at back-projection image caused by occlusions. We can use the morphology operations like dilating for example. Use Camshift to track the circular object starting in a window around the initial circle.
Conveniently for us, Camshift are included in opencv!
I encourage you to read the original Camshift paper to learn more about it:
Computer Vision face tracking for use in a perceptual User
Interface
Gary R. Bradski, Microcomputer Lab, Santa Clara, CA, Intel Corporation
Link to the paper
Code (c + +, using OpenCV):
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/core/core.hpp"
Include "OPENCV2/VIDEO/TRACKING.HPP" #include <tuple> using namespace CV;
using namespace Std;
This is used to obtain a Windows inside the image,//and cut it around the image borders. Rect Getroi (Size const imagesize, point Const Center, int windowsize) {point topleft (center.x-windowsize/2, cent
ER.Y-WINDOWSIZE/2); if (Topleft.x + windowsize > ImageSize.Width | | topleft.y + windowsize > Imagesize.height) {w
indowsize = min (imagesize.width-topleft.x, IMAGESIZE.HEIGHT-TOPLEFT.Y);
Return Rect (Topleft.x, Topleft.y, WindowSize, windowsize);
}//this is used to find pixels this likely belong to the circular object//we to wish.
Mat histogrambackprojectionfortracking (Mat const& image, Rect const window) {Const int sizes[] = {256,256,256};
Float rrange[] = {0,255}; Float GrangE[] = {0,255};
Float brange[] = {0,255};
const FLOAT *ranges[] = {Rrange,grange,brange};
const int channels[] = {0, 1, 2};
Mat ROI = image (window);
Mat hist;
if (image.channels () = = 3) calchist (&roi, 1, channels, Mat (), Hist, 3, sizes, ranges);
else Calchist (&roi, 1, &channels[0], Mat (), hist, 1, &sizes[0], &ranges[0]);
Mat backproj;
Calcbackproject (&image, 1, channels, Hist, backproj, ranges);
return backproj;
}//return a new circle by using Camshift to track the object around the initial circle. Tuple<point, int> houghshift (Point Const Center, int const RADIUS, Mat const& image) {Mat backproj = Histog
Rambackprojectionfortracking (Image, Getroi (Image.size (), center, RADIUS));
Fill HOLES:CV::d ilate (Backproj, Backproj, Cv::mat (), CV::P oint ( -1,-1));
CV::d ilate (Backproj, Backproj, Cv::mat (), CV::P oint ( -1,-1));
const int windowtrackingsize = 4 * RADIUS; ROtatedrect track = Camshift (Backproj, Getroi (Image.size (), center, Termcriteria (cv_termcrit_eps |
Cv_termcrit_iter, 10, 1));
Return Make_tuple (Track.center, (track.size.width + track.size.height)/4);
int main (int argc, char** argv) {Mat image = Cv::imread ("Image.jpg"); Mat before, after; Image.copyto (before);
Image.copyto (after); Mat Gray;
Cv::cvtcolor (image, Gray, Cv_bgr2gray);
Std::vector<cv::vec3f> circles;
Houghcircles (gray, circles, cv_hough_gradient, 2, GRAY.COLS/3, GRAY.COLS/20, GRAY.COLS/5);
for (int i = 0; i < circles.size (); ++i) {Auto Circle = Houghshift (Point (Circles[i][0), circles[i][1])
CIRCLES[I][2], image);
Circle (before, point (Circles[i][0], circles[i][1]), circles[i][2], Scalar (128, 128, 30), 2);
Circle (After, get<0> (circle), get<1> (circle), Scalar (255, 0, 0), 2);
} imshow ("Initial circles", before); Imshow ("Refined Circles", after);
Waitkey (-1);
return 0; }
From:http://jacobcv.blogspot.com/2014/04/refining-hough-transform-with-camshift.html