Object tracking
Object tracking based on color histogram and real-time back projection
Process
- Modeling color histogram of selected object
- Calculate histogram similarity
- Back projection
- Mean shift process (clustering of pixels with back projected weights)
- Update object position and parameters after tracking
Additional functions
- Dynamic navigation area
- Dynamic change of object color histogram
- Dynamic change of object size
Codes
- Calculate color histogram
double * hists = (double*)calloc(param.hist_bins, sizeof(double)), hist_size = 256 / param.hist_bins;int eWidth = min(rc.x + rc.width, img.size().width), eHeight = min(rc.y + rc.height, img.size().height);for (int i = rc.x; i < eWidth; ++i) for (int j = rc.y; j < eHeight; ++j) hists[matrixAt(img, i, j) / (int)hist_size]++;
double total = 0;for (int i = 0; i < param.hist_bins; ++i) total += hists[i] * hists[i];total = sqrt(total);for (int i = 0; i < param.hist_bins; ++i) hists[i] /= total;
return hists;- Back projection
Mat imx = hsv.clone();for (int i = 0; i < hsv.cols; ++i) for (int j = 0; j < hsv.rows; ++j) { w = this->objectHists[matrixAt(imx, i, j) / param.hist_bins]; double pixel[] = { 255 * w, 255 * w, 255 * w }; matrixSet(imx, i, j, pixel); }- Mean shift
Mat hsv;cvtColor(img, hsv, CV_BGR2HSV);Rect nRect = myRect, temp, bRect = myRect;double nX = 0, nY = 0, tW = 0, w;do { tW = 0, nX = 0; nY = 0; myRect = nRect;
// set searching area temp = Rect(max(nRect.x - (int)param.search_range, 0), max(nRect.y - (int)param.search_range, 0), min(nRect.width + (int)param.search_range * 2, hsv.rows), min(nRect.height + (int)param.search_range * 2, hsv.cols)); double sRatioWidth = temp.width / param.sampling, sRatioHeight = temp.height / param.sampling; for (int i = 0; i <= temp.width / 2; i+=sRatioWidth) for (int j = 0; j <= temp.height / 2; j+=sRatioHeight) { w = mySimilarity(hsv, Rect(temp.x + (temp.width / 2) + i, temp.y + (temp.height / 2) + j, nRect.width, nRect.height), this->objectHists); tW += w; nX += w * (temp.x + (temp.width / 2) + i); nY += w * (temp.y + (temp.height / 2) + j); if (i != 0 || j != 0) { w = mySimilarity(hsv, Rect(temp.x + (temp.width / 2) - i, temp.y + (temp.height / 2) - j, nRect.width, nRect.height), this->objectHists); tW += w; nX += w * (temp.x + (temp.width / 2) - i); nY += w * (temp.y + (temp.height / 2) - j); } } nX /= tW; nY /= tW;
// get mean of w, if w > 0.25 make range narrow, or not make extend; double twRatio = tW / ((temp.width / sRatioWidth) * (temp.height / sRatioHeight)); param.search_range *= (twRatio > (EXTEND_LIMIT) ? 1 - twRatio : (1 - EXTEND_LIMIT) +twRatio);
nRect = Rect(max((int)nX - nRect.width / 2, 0), max((int)nY - nRect.height / 2, 0), myRect.width, myRect.height);} while (sqrt(pow(myRect.x - nRect.x, 2) + pow(myRect.y - nRect.y, 2)) > param.search_range);