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);