// Computes specificity of the model by comparing random samples of the model with the test mashes. float specificity(Logger& logger, StatisticalModelType::Pointer model, const MeshDataList& testMeshes, unsigned numberOfSamples) { // draw a number of samples and compute its distance to the closest training dataset double accumulatedDistToClosestTrainingShape = 0; for (unsigned i = 0; i < numberOfSamples; i++) { MeshType::Pointer sample = model->DrawSample(); double minDist = std::numeric_limits<double>::max(); for (MeshDataList::const_iterator it = testMeshes.begin(); it != testMeshes.end(); ++it) { MeshType::Pointer testMesh = it->first; // before we compute the distances between the meshes, we normalize the scale by scaling them // to optimally match the mean. This makes sure that models that include scale and those that have them normalized // ar etreated the same. MeshType::Pointer sampledScaledToMean = normalizeScale(sample, model->DrawMean()); MeshType::Pointer testScaledToMean = normalizeScale(testMesh, model->DrawMean()); double dist = computeAverageDistance(testScaledToMean, sampledScaledToMean, ConfigParameters::numSamplingPointsSpecificity); logger.Get(logINFO) << "distance " << dist << std::endl; if (dist < minDist) { minDist = dist; } } logger.Get(logINFO) << "closest distance for sample " << i << ": " << minDist << std::endl; accumulatedDistToClosestTrainingShape += minDist; } double avgDist = accumulatedDistToClosestTrainingShape / numberOfSamples; logger.Get(logINFO) << "average distance " << avgDist << std::endl; return avgDist; }
bool TemporalVarianceBGModule::run() { uchar *ptr_imgData = m_data->currentImage->bits(); if(imgARGB32.empty() || imgARGB32.data == NULL) { this->height = m_data->currentImage->height(); this->width = m_data->currentImage->width(); this->imgARGB32 = cv::Mat(height, width, CV_8UC4 ); } memcpy(imgARGB32.data, ptr_imgData, m_data->currentImage->height()*m_data->currentImage->bytesPerLine()); #ifdef __OPENCV3__ cv::cvtColor(imgARGB32, currImgC3, cv::COLOR_RGBA2BGR); cv::cvtColor(currImgC3, currGrayImg, cv::COLOR_BGR2GRAY ); #else cv::cvtColor(imgARGB32, currImgC3, CV_RGBA2BGR); cv::cvtColor(currImgC3, currGrayImg, CV_BGR2GRAY ); #endif ptr_currGrayImg = currGrayImg.data; if(m_tuningActivated) tuneParameters(); if(firstTime) { this->height = m_data->currentImage->height(); this->width = m_data->currentImage->width(); ptr_fgMean = (float *) malloc(sizeof(float) * width* height ); ptr_fgMean2 = (float *) malloc(sizeof(float) * width*height ); ptr_fgVar = (float *) malloc(sizeof(float) * width*height ); memset(ptr_fgVar, 0, sizeof(float) * width*height); ptr_bgMean = (float *) malloc(sizeof(float) * width*height ); memset(ptr_bgMean, 0, sizeof(float) * width*height); ptr_bgMean2 = (float *) malloc(sizeof(float) * width*height ); memset(ptr_bgMean2, 0, sizeof(float) * width*height); ptr_bgVar = (float *) malloc(sizeof(float) * width*height ); memset(ptr_bgVar, 0, sizeof(float) * width*height); ptr_fgVarMask = (uchar *) malloc(sizeof(uchar)* width*height ); ptr_fgMask= (uchar *) malloc(sizeof(uchar)* width*height ); if(m_data->fgImage == NULL) { m_data->fgImage = new QImage(width,height, QImage::Format_Indexed8); m_data->fgImage->setColorTable(*(m_data->grayScaleTable)); memset(m_data->fgImage->bits(), 0, height*m_data->fgImage->bytesPerLine()); } if(m_data->temporalVariance == NULL) { m_data->temporalVariance = new QImage(width,height, QImage::Format_Indexed8); m_data->temporalVariance->setColorTable(*(m_data->grayScaleTable)); memset(m_data->temporalVariance->bits(), 0, height*m_data->temporalVariance->bytesPerLine()); } if(m_data->reliabilityMap == NULL || m_data->reliabilityMap->isNull()) { m_data->reliabilityMap = new QImage(width,height, QImage::Format_ARGB32); } for(int i = 0; i < height*width; i++) { ptr_fgMean[i] = ptr_currGrayImg[i]; ptr_fgMean2[i] = ptr_currGrayImg[i]*ptr_currGrayImg[i]; ptr_bgMean[i] = ptr_currGrayImg[i]; ptr_bgMean2[i] = ptr_currGrayImg[i]*ptr_currGrayImg[i]; } reliability = cv::Mat(height, width, CV_8UC1); ptr_reliability = reliability.data; #ifdef __OPENCV3__ roi = cv::imread("TVroi.png", cv::IMREAD_GRAYSCALE ); //TODO: hacer esto mediante un atributo #else roi = cv::imread("TVroi.png", CV_LOAD_IMAGE_GRAYSCALE ); //TODO: hacer esto mediante un atributo #endif firstTime = false; return true; } else if(m_data->firstOfCycle) { //If this is true, it implies that acquisition cycling is activated. //Structures must be reinitialized, to avoid parasite data. memset(ptr_fgVar, 0, sizeof(float) * width*height); memset(ptr_bgMean, 0, sizeof(float) * width*height); memset(ptr_bgMean2, 0, sizeof(float) * width*height); memset(ptr_bgVar, 0, sizeof(float) * width*height); if(m_data->fgImage != NULL) memset(m_data->fgImage->bits(), 0, height*m_data->fgImage->bytesPerLine()); if(m_data->temporalVariance != NULL) memset(m_data->temporalVariance->bits(), 0, height*m_data->temporalVariance->bytesPerLine()); if(m_data->reliabilityMap == NULL || m_data->reliabilityMap->isNull()) m_data->reliabilityMap = new QImage(width,height, QImage::Format_ARGB32); for(int i = 0; i < height*width; i++) { ptr_fgMean[i] = ptr_currGrayImg[i]; ptr_fgMean2[i] = ptr_currGrayImg[i]*ptr_currGrayImg[i]; ptr_bgMean[i] = ptr_currGrayImg[i]; ptr_bgMean2[i] = ptr_currGrayImg[i]*ptr_currGrayImg[i]; } return true; } for(int i = 0; i < width* height; i++) { //fg model ptr_fgMean[i] =( (fgSizeWindow - 1)*ptr_fgMean[i] + ptr_currGrayImg[i])/fgSizeWindow; ptr_fgMean2[i] =( (fgSizeWindow - 1)*ptr_fgMean2[i] + ptr_currGrayImg[i]*ptr_currGrayImg[i])/fgSizeWindow; ptr_fgVar[i] = ptr_fgMean2[i] - ptr_fgMean[i]*ptr_fgMean[i]; if(ptr_fgVar[i] < TRUNCATE_VALUE) ptr_fgVar[i] = 0.0; ptr_fgVarMask[i] = (ptr_fgVar[i] > this->fgVarianceThreshold)? FOREGROUND: BACKGROUND; //bg model if(ptr_fgVarMask[i] == BACKGROUND) { ptr_bgMean[i] = ( (bgSizeWindow - 1)*ptr_bgMean[i] + ptr_currGrayImg[i])/bgSizeWindow; ptr_bgMean2[i] = ( (bgSizeWindow - 1)*ptr_bgMean2[i] + ptr_currGrayImg[i]*ptr_currGrayImg[i])/bgSizeWindow; ptr_bgVar[i] = ptr_bgMean2[i] - ptr_bgMean[i]*ptr_bgMean[i]; if(ptr_bgVar[i] < TRUNCATE_VALUE) ptr_bgVar[i] = 0.0; } } ptr_dataVarMask = m_data->temporalVariance->bits(); memcpy(ptr_dataVarMask, ptr_fgVarMask, width* height); //background update bgVarMean = 0.0, numBgPixels = 0.0; for(int i = 0; i < width* height; i++) { if( ptr_bgVar[i] != 0.0) { bgVarMean += sqrt(ptr_bgVar[i]); numBgPixels++; } } bgVarMean /= numBgPixels; detectionThreshold = this->detectionFactorThreshold * bgVarMean; featureMap = cv::Mat(height,width, CV_8UC1); for(int i = 0; i < width* height; i++) { value = sqrt(ptr_fgVar[i])* confidenceOfForeground(fabs(ptr_bgMean[i] - ptr_currGrayImg[i] ), sqrt(ptr_bgVar[i])); //value in [0,255] featureMap.data[i] = normalizeScale(value); ptr_reliability[i] = normalizeBothSideScale(value, detectionThreshold); if(roi.data !=NULL && roi.data[i] == BACKGROUND) //El ROI solo se usa para filtrar la clasificacion final ptr_fgMask[i] = BACKGROUND; else ptr_fgMask[i] = (value > detectionThreshold)? FOREGROUND: BACKGROUND; } uchar *ptr_dataFgImg= m_data->fgImage->bits(); memcpy(ptr_dataFgImg, ptr_fgMask, height*m_data->fgImage->bytesPerLine()); reliabilityThermal = ThermalColor::reliabilityToThermal(reliability); #ifdef __OPENCV3__ cv::cvtColor(reliabilityThermal, imgARGB32, cv::COLOR_BGR2RGBA); #else cv::cvtColor(reliabilityThermal, imgARGB32, CV_BGR2RGBA); #endif memcpy(m_data->reliabilityMap->bits(), imgARGB32.data, height * m_data->reliabilityMap->bytesPerLine()); if(displayFeatureMap) { cv::namedWindow("featureMap"); cv::imshow("featureMap",featureMap); } if(displayFirstModel) { cv::Mat firstModel (height, width, CV_8UC1, this->ptr_fgVarMask); cv::namedWindow("firstModelFg"); cv::imshow("firstModelFg",firstModel); } /* if(displaySecondModel) // second model is calculated on-line { cv::namedWindow("secondModelFg"); cv::imshow("secondModelFg",featureMap); } */ //save results, //TODO: make it an option avaible from parameters. // m_data->fgImage->save("TV_fg_" + QString::number(m_data->frameNumber) + ".jpg"); // m_data->reliabilityMap->save("TV_feature_" + QString::number(m_data->frameNumber) + ".jpg"); return true; }