void CmSaliencyRC::SmoothByHist(CMat &img3f, Mat &sal1f, float delta) { //imshow("Before", sal1f); imshow("Src", img3f); // Quantize colors CV_Assert(img3f.size() == sal1f.size() && img3f.type() == CV_32FC3 && sal1f.type() == CV_32FC1); Mat idx1i, binColor3f, colorNums1i; int binN = Quantize(img3f, idx1i, binColor3f, colorNums1i); //CmShow::HistBins(binColor3f, colorNums1i, "Frequency"); // Get initial color saliency Mat _colorSal = Mat::zeros(1, binN, CV_64FC1); int rows = img3f.rows, cols = img3f.cols;{ double* colorSal = (double*)_colorSal.data; if (img3f.isContinuous() && sal1f.isContinuous()) cols *= img3f.rows, rows = 1; for (int y = 0; y < rows; y++){ const int* idx = idx1i.ptr<int>(y); const float* initialS = sal1f.ptr<float>(y); for (int x = 0; x < cols; x++) colorSal[idx[x]] += initialS[x]; } const int *colorNum = (int*)(colorNums1i.data); for (int i = 0; i < binN; i++) colorSal[i] /= colorNum[i]; normalize(_colorSal, _colorSal, 0, 1, NORM_MINMAX, CV_32F); } // Find similar colors & Smooth saliency value for color bins vector<vector<CostfIdx>> similar(binN); // Similar color: how similar and their index Vec3f* color = (Vec3f*)(binColor3f.data); cvtColor(binColor3f, binColor3f, CV_BGR2Lab); for (int i = 0; i < binN; i++){ vector<CostfIdx> &similari = similar[i]; similari.push_back(make_pair(0.f, i)); for (int j = 0; j < binN; j++) if (i != j) similari.push_back(make_pair(vecDist<float, 3>(color[i], color[j]), j)); sort(similari.begin(), similari.end()); } cvtColor(binColor3f, binColor3f, CV_Lab2BGR); //CmShow::HistBins(binColor3f, _colorSal, "BeforeSmooth", true); SmoothSaliency(colorNums1i, _colorSal, delta, similar); //CmShow::HistBins(binColor3f, _colorSal, "AfterSmooth", true); // Reassign pixel saliency values float* colorSal = (float*)(_colorSal.data); for (int y = 0; y < rows; y++){ const int* idx = idx1i.ptr<int>(y); float* resSal = sal1f.ptr<float>(y); for (int x = 0; x < cols; x++) resSal[x] = colorSal[idx[x]]; } //imshow("After", sal1f); //waitKey(0); }
int CmSaliencyRC::Quantize(CMat& img3f, Mat &idx1i, Mat &_color3f, Mat &_colorNum, double ratio, const int clrNums[3]) { float clrTmp[3] = {clrNums[0] - 0.0001f, clrNums[1] - 0.0001f, clrNums[2] - 0.0001f}; int w[3] = {clrNums[1] * clrNums[2], clrNums[2], 1}; CV_Assert(img3f.data != NULL); idx1i = Mat::zeros(img3f.size(), CV_32S); int rows = img3f.rows, cols = img3f.cols; if (img3f.isContinuous() && idx1i.isContinuous()){ cols *= rows; rows = 1; } // Build color pallet map<int, int> pallet; for (int y = 0; y < rows; y++) { const float* imgData = img3f.ptr<float>(y); int* idx = idx1i.ptr<int>(y); for (int x = 0; x < cols; x++, imgData += 3) { idx[x] = (int)(imgData[0]*clrTmp[0])*w[0] + (int)(imgData[1]*clrTmp[1])*w[1] + (int)(imgData[2]*clrTmp[2]); pallet[idx[x]] ++; } } // Find significant colors int maxNum = 0; { int count = 0; vector<pair<int, int>> num; // (num, color) pairs in num num.reserve(pallet.size()); for (map<int, int>::iterator it = pallet.begin(); it != pallet.end(); it++) num.push_back(pair<int, int>(it->second, it->first)); // (color, num) pairs in pallet sort(num.begin(), num.end(), std::greater<pair<int, int>>()); maxNum = (int)num.size(); int maxDropNum = cvRound(rows * cols * (1-ratio)); for (int crnt = num[maxNum-1].first; crnt < maxDropNum && maxNum > 1; maxNum--) crnt += num[maxNum - 2].first; maxNum = min(maxNum, 256); // To avoid very rarely case if (maxNum <= 10) maxNum = min(10, (int)num.size()); pallet.clear(); for (int i = 0; i < maxNum; i++) pallet[num[i].second] = i; vector<Vec3i> color3i(num.size()); for (unsigned int i = 0; i < num.size(); i++) { color3i[i][0] = num[i].second / w[0]; color3i[i][1] = num[i].second % w[0] / w[1]; color3i[i][2] = num[i].second % w[1]; } for (unsigned int i = maxNum; i < num.size(); i++) { int simIdx = 0, simVal = INT_MAX; for (int j = 0; j < maxNum; j++) { int d_ij = vecSqrDist<int, 3>(color3i[i], color3i[j]); if (d_ij < simVal) simVal = d_ij, simIdx = j; } pallet[num[i].second] = pallet[num[simIdx].second]; } } _color3f = Mat::zeros(1, maxNum, CV_32FC3); _colorNum = Mat::zeros(_color3f.size(), CV_32S); Vec3f* color = (Vec3f*)(_color3f.data); int* colorNum = (int*)(_colorNum.data); for (int y = 0; y < rows; y++) { const Vec3f* imgData = img3f.ptr<Vec3f>(y); int* idx = idx1i.ptr<int>(y); for (int x = 0; x < cols; x++) { idx[x] = pallet[idx[x]]; color[idx[x]] += imgData[x]; colorNum[idx[x]] ++; } } for (int i = 0; i < _color3f.cols; i++) color[i] /= (float)colorNum[i]; return _color3f.cols; }