int determine_optimal_threshold( CvHistogram* hist ) { // TO DO: Given a 1-D CvHistogram you need to determine and return the optimal threshold value. // NOTES: Assume there are 256 elements in the histogram. // To get the histogram value at index i // int histogram_value_at_i = ((int) *cvGetHistValue_1D(hist, i)); int histogram_value_at[256]; // amount of pixel of every greyscale value int temp_threshold_sum = 0; //for calculating the initial_threshold int threshold_sum = 0; int initial_threshold = 0; //T(1) int final_threshold = 0; //T(n+1) int background = 0; //summation of greyscale values of background int object = 0; //summation of greyscale values of object int threshold_1 = 0; int threshold_2 = 0; //determine the first threshold. //I initial the first threshold value by finding the value which divides the area of the curve into halves. for(int i = 0; i< 256; i++) { histogram_value_at[i] = ((int) *cvGetHistValue_1D(hist, i)); threshold_sum += histogram_value_at[i]; } while(temp_threshold_sum < (threshold_sum/2)) { temp_threshold_sum += histogram_value_at[initial_threshold++]; } threshold_1 = initial_threshold; //optimal thresholding while(1) { object = sum_of_pixel_value(histogram_value_at, 0, threshold_1)/sum_of_pixel_number(histogram_value_at, 0, threshold_1); background = sum_of_pixel_value(histogram_value_at, threshold_1, 256)/sum_of_pixel_number(histogram_value_at, threshold_1, 256); threshold_2 = threshold_1; threshold_1 = (object + background)/2; if(abs(threshold_2 - threshold_1) < 1) //T(n) = T(n+1) approximately { break; } //else continue doing the loop until T(n) = T(n+1) } return threshold_1; }
void CvAdaptiveSkinDetector::Histogram::mergeWith(CvAdaptiveSkinDetector::Histogram *source, double weight) { float myweight = (float)(1-weight); float maxVal1 = 0, maxVal2 = 0, *f1, *f2, ff1, ff2; cvGetMinMaxHistValue(source->fHistogram, NULL, &maxVal2); if (maxVal2 > 0 ) { cvGetMinMaxHistValue(fHistogram, NULL, &maxVal1); if (maxVal1 <= 0) { for (int i = 0; i < HistogramSize; i++) { f1 = cvGetHistValue_1D(fHistogram, i); f2 = cvGetHistValue_1D(source->fHistogram, i); (*f1) = (*f2); } } else { for (int i = 0; i < HistogramSize; i++) { f1 = cvGetHistValue_1D(fHistogram, i); f2 = cvGetHistValue_1D(source->fHistogram, i); ff1 = ((*f1)/maxVal1)*myweight; if (ff1 < 0) ff1 = -ff1; ff2 = (float)(((*f2)/maxVal2)*weight); if (ff2 < 0) ff2 = -ff2; (*f1) = (ff1 + ff2); } } } };
float Histogram::getValue(int idx0, int idx1, int idx2) const { switch (m_histogram->mat.dims) { case 1: return *cvGetHistValue_1D(m_histogram, idx0); case 2: return *cvGetHistValue_2D(m_histogram, idx0, idx1); case 3: return *cvGetHistValue_3D(m_histogram, idx0, idx1, idx2); } return NULL; }
int CvAdaptiveSkinDetector::Histogram::findCoverageIndex(double surfaceToCover, int defaultValue) { float s = 0; for (int i = 0; i < HistogramSize; i++) { s += *cvGetHistValue_1D( fHistogram, i ); if (s >= surfaceToCover) { return i; } } return defaultValue; };
//-------------------------------------------------------------- void testApp::computeDepthHistogram (ofxCvGrayscaleImage depthImage) { // Compute the histogram of the depth-colored difference-from-background image. IplImage* iplDepthImg = depthImage.getCvImage(); cvCalcHist( &iplDepthImg, depthHistogram, 0, NULL ); float *depthHistArr = cvGetHistValue_1D (depthHistogram, 0); int maxVal = 0; int startIndex = 1; // don't count black pixels. for (int i=startIndex; i<depthHistogramSize; i++) { if (depthHistArr[i] > maxVal) { maxVal = depthHistArr[i]; } } for (int i=0; i<depthHistogramSize; i++) { depthHistogramData[i] = depthHistArr[i] / (float)maxVal; } }
void CvAdaptiveSkinDetector::Histogram::findCurveThresholds(int &x1, int &x2, double percent) { float sum = 0; for (int i = 0; i < HistogramSize; i++) { sum += *cvGetHistValue_1D( fHistogram, i ); } x1 = findCoverageIndex(sum * percent, -1); x2 = findCoverageIndex(sum * (1-percent), -1); if (x1 == -1) x1 = GSD_HUE_LT; else x1 += GSD_HUE_LT; if (x2 == -1) x2 = GSD_HUE_UT; else x2 += GSD_HUE_LT; };
void AdaptiveHistogramCamshift::AdaptHistogram(IplImage* hue, IplImage* mask, IplImage* out) { // Prepare to analyze new track window const CvRect& updateHistRect = m_trackCompRect; // Now subdivide the track window and sum all pixels in each square // subdivision of size m_sBox using pixel values given by the // current hustogram. When we are done, we will normalize the sum // from each subdivision and then be able to tell roughly how // similar each subregion is to the track histogram. // Make sure box size is greater than or equal to 2, and protect from // changes made in GUI const int sBox = std::max(m_sBox, 2); if (sBox != m_sBox) { m_sBox = sBox; cvSetTrackbarPos(ControlNames[ControlName_SBox], m_controlsGUIWndName.c_str(), sBox); } std::vector<float> subdivs; int numRows, numCols; SubdivideSumTrackWnd(sBox, &numRows, &numCols, &subdivs); // Check window is less than sBox in size. if (subdivs.empty()) { return; } // Histogram for image subdivisions for (int i = 0; i < m_histDims; ++i) { float *bin = cvGetHistValue_1D(m_histTrackWnd, i); *bin = 0; } // Find the max vlaue of the subdivisions float maxVal = *std::max_element(subdivs.begin(), subdivs.end());; // DEBUG maxval //printf("maxVal: %f\n", maxVal); // Step through all subdivisions and weight them into a new histogram // if they are greater than minVal. The weight function is r^2 where // r is the ratio of the subdivision value to the max subdivision // value. if (maxVal > 0) { float minVal = maxVal * 0.125f; float* subdivsCur = &subdivs[0]; for (int i = 0; i < numRows; ++i) { for (int j = 0; j < numCols; ++j, ++subdivsCur) { // Create a box around this area CvPoint roiP1 = cvPoint(updateHistRect.x + sBox * j, updateHistRect.y + sBox * i); CvPoint roiP2 = cvPoint(roiP1.x + sBox, roiP1.y + sBox); if (*subdivsCur < minVal) { if(*subdivsCur > (minVal * 0.0625)) { // Get ratio to max subdivision float ratioMaxSubdiv = *subdivsCur / maxVal; // Get color of surrounding box CvScalar boxColor = colors[GREEN]; for (int colorInd = 0; colorInd < 3; ++colorInd) { boxColor.val[colorInd] *= ratioMaxSubdiv; } // Draw the box (darker green means less weight) if (out) { cvRectangle(out, roiP1, roiP2, boxColor, 1); } } else { // Draw a red box around this subdivision since it is not used if (out) { cvRectangle(out, roiP1, roiP2, colors[RED], 1 ); } } } else { // Get ratio to max subdivision float ratioMaxSubdiv = *subdivsCur / maxVal; // Get weight into histogram of track window float weightVal = ratioMaxSubdiv * ratioMaxSubdiv; // DEBUG weights //printf("w %d: %f\t", j, weightVal); // Get color of surrounding box CvScalar boxColor = colors[GREEN]; for (int colorInd = 0; colorInd < 3; ++colorInd) { boxColor.val[colorInd] *= ratioMaxSubdiv; } // Draw the box (darker green means less weight) if (out) { cvRectangle(out, roiP1, roiP2, boxColor, 1); } // Weight this subdivision into the histogram for the track window CvRect thisSubdivRect = cvRect(roiP1.x, roiP1.y, sBox, sBox); cvSetImageROI(hue, thisSubdivRect); cvSetImageROI(mask, thisSubdivRect); cvCalcHist(&hue, m_histSubdiv, 0, mask); cvResetImageROI(hue); cvResetImageROI(mask); // Weight this into the track window histogram for (int binNum = 0; binNum < m_histDims; ++binNum) { float* thisBin = cvGetHistValue_1D(m_histTrackWnd, binNum); *thisBin *= (1.0f - weightVal); *thisBin += static_cast<float>(cvGetReal1D(m_histSubdiv->bins, binNum)) * weightVal; } } } // DEBUG weights //printf("\n"); } // DEBUG weights //printf("\n"); } // DEBUG histograms //printf("Wnd BEFORE WT\n"); //for( int i = 0; i < m_histDims; i++ ) { // float *bin = cvGetHistValue_1D( m_histTrackWnd, i ); // printf("%2d: %3.1f ", i, *bin); // if( 0 == (i+1) % 8 ) { // printf("\n"); // } //} // Now scale track window histogram to tracking histogram scale float trackWndHistMaxVal; cvGetMinMaxHistValue(m_histTrackWnd, 0, &trackWndHistMaxVal, 0, 0); cvConvertScale(m_histTrackWnd->bins, m_histTrackWnd->bins, trackWndHistMaxVal ? HIST_SCALE / trackWndHistMaxVal : 0., 0); // Use aging to weight track window histogram into tracking histogram float averageBin = 0; for (int binNum = 0; binNum < m_histDims; ++binNum) { float* thisBin = cvGetHistValue_1D(m_hist, binNum); *thisBin *= (1.0f - (m_ageRatio / 100.0f)); *thisBin += static_cast<float>(cvGetReal1D(m_histTrackWnd->bins, binNum)) * (m_ageRatio / 100.0f); averageBin += *thisBin; } averageBin /= m_histDims; // DEBUG average bin //printf("Avg bin: %f.\n", averageBin); // See if this histogram is dying //if( averageBin < SMALLEST_AVG_HIST_BIN ) { // cvConvertScale( m_hist->bins, m_hist->bins, SMALLEST_AVG_HIST_BIN / averageBin, 0 ); // DEBUG averageBin //printf("Hist saved for average bin: %f\n", averageBin); //} // DEBUG track hist //printf("Track\n"); //for( int i = 0; i < m_histDims; i++ ) { // float *bin = cvGetHistValue_1D( m_hist, i ); // printf("%2d: %3.1f ", i, *bin); // if( 0 == (i+1) % 8 ) { // printf("\n"); // } //} //printf("\n"); // Now compute histogram image cvZero(m_histImg); for (int i = 0; i < m_histDims; ++i) { const double raw = cvGetReal1D(m_hist->bins, i) * (m_histImg->height / HIST_SCALE); const int val = cvRound(raw); CvScalar color = hsv2rgb((i * m_histRanges[1]) / m_histDims); cvRectangle(m_histImg, cvPoint(i * m_binWidth, m_histImg->height), cvPoint((i + 1) * m_binWidth, m_histImg->height - val), color, -1, 8, 0); } // Show histogram if (m_showHistogram) { ShowHistogram(); } }