typename MaskedHistogramGenerator<TBinValue, TQuadrantProperties>::HistogramType MaskedHistogramGenerator<TBinValue, TQuadrantProperties>::ComputeMaskedScalarImageHistogram
    (const TImage* const image, const itk::ImageRegion<2>& imageRegion,
     const Mask* const mask, const itk::ImageRegion<2>& maskRegion, const unsigned int numberOfBins,
     const TRangeValue& rangeMin, const TRangeValue& rangeMax, const bool allowOutside, const HoleMaskPixelTypeEnum& maskValue)
{
  std::vector<itk::Index<2> > maskIndices = ITKHelpers::GetPixelsWithValueInRegion(mask, maskRegion, maskValue);

  // Compute the corresponding locations in the imageRegion
  std::vector<itk::Index<2> > imageIndices(maskIndices.size());
  itk::Offset<2> maskRegionToImageRegionOffset = imageRegion.GetIndex() - maskRegion.GetIndex(); // The offset from the maskRegion to the imageRegion
  for(size_t i = 0; i < maskIndices.size(); ++i)
  {
    imageIndices[i] = maskIndices[i] + maskRegionToImageRegionOffset;
  }

  HistogramType histogram;

  // Get this channels masked scalar values
  std::vector<typename TImage::PixelType> validPixels =
      ITKHelpers::GetPixelValues(image, imageIndices);

  // Compute the histogram of the scalar values
  if(allowOutside)
  {
    histogram = HistogramGeneratorType::ScalarHistogramAllowOutside(validPixels, numberOfBins, rangeMin, rangeMax);
  }
  else
  {
    histogram = HistogramGeneratorType::ScalarHistogram(validPixels, numberOfBins, rangeMin, rangeMax);
  }

  return histogram;
}
typename MaskedHistogramGenerator<TBinValue, TQuadrantProperties>::HistogramType MaskedHistogramGenerator<TBinValue, TQuadrantProperties>::ComputeMaskedImage1DHistogram(
                const itk::VectorImage<TComponent, 2>* image,
                const itk::ImageRegion<2>& imageRegion,
                const Mask* const mask,
                const itk::ImageRegion<2>& maskRegion,
                const unsigned int numberOfBinsPerDimension,
                const TRangeContainer& rangeMins,
                const TRangeContainer& rangeMaxs, const bool allowOutside, const HoleMaskPixelTypeEnum& maskValue)
{
  // For VectorImage, we must use VectorImageToImageAdaptor

  typedef itk::VectorImage<TComponent, 2> ImageType;
  typedef itk::Image<TComponent, 2> ScalarImageType;

  std::vector<itk::Index<2> > maskIndices = ITKHelpers::GetPixelsWithValueInRegion(mask, maskRegion, maskValue);

  // Compute the corresponding locations in the imageRegion
  std::vector<itk::Index<2> > imageIndices(maskIndices.size());
  itk::Offset<2> maskRegionToImageRegionOffset = imageRegion.GetIndex() - maskRegion.GetIndex(); // The offset from the maskRegion to the imageRegion
  for(size_t i = 0; i < maskIndices.size(); ++i)
  {
    imageIndices[i] = maskIndices[i] + maskRegionToImageRegionOffset;
  }

  HistogramType concatenatedHistograms;

  for(unsigned int channel = 0; channel < image->GetNumberOfComponentsPerPixel(); ++channel)
  {
    // Extract the channel

    typedef itk::VectorImageToImageAdaptor<TComponent, 2> ImageAdaptorType;
    typename ImageAdaptorType::Pointer adaptor = ImageAdaptorType::New();
    adaptor->SetExtractComponentIndex(channel);
    adaptor->SetImage(const_cast<ImageType*>(image));

    // Get this channels masked scalar values
    std::vector<typename ScalarImageType::PixelType> validPixels =
        ITKHelpers::GetPixelValues(adaptor.GetPointer(), imageIndices);

    // Compute the histogram of the scalar values
    HistogramType histogram;
    if(allowOutside)
    {
      histogram = HistogramGeneratorType::ScalarHistogramAllowOutside(validPixels, numberOfBinsPerDimension,
                                                                      rangeMins[channel], rangeMaxs[channel]);
    }
    else
    {
      histogram = HistogramGeneratorType::ScalarHistogram(validPixels, numberOfBinsPerDimension,
                                                          rangeMins[channel], rangeMaxs[channel]);
    }
    concatenatedHistograms.insert(concatenatedHistograms.end(), histogram.begin(), histogram.end());
  }

  return concatenatedHistograms;
}
Пример #3
0
void CUDASolverBundling::computeMaxResidual(SolverInput& solverInput, SolverParameters& parameters, unsigned int revalidateIdx)
{
	if (m_timer) m_timer->startEvent(__FUNCTION__);
	if (parameters.weightSparse > 0.0f) {
		evalMaxResidual(solverInput, m_solverState, m_solverExtra, parameters, NULL);//m_timer);
		// copy to cpu
		unsigned int n = (solverInput.numberOfCorrespondences + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK;
		cutilSafeCall(cudaMemcpy(m_solverExtra.h_maxResidual, m_solverExtra.d_maxResidual, sizeof(float) * n, cudaMemcpyDeviceToHost));
		cutilSafeCall(cudaMemcpy(m_solverExtra.h_maxResidualIndex, m_solverExtra.d_maxResidualIndex, sizeof(int) * n, cudaMemcpyDeviceToHost));
		// compute max
		float maxResidual = 0.0f; int maxResidualIndex = 0;
		for (unsigned int i = 0; i < n; i++) {
			if (maxResidual < m_solverExtra.h_maxResidual[i]) {
				maxResidual = m_solverExtra.h_maxResidual[i];
				maxResidualIndex = m_solverExtra.h_maxResidualIndex[i];
			}
		}
#ifdef NEW_GUIDED_REMOVE

		//if (solverInput.numberOfImages == 51) {
		//	SensorData sd; sd.loadFromFile("../data/iclnuim/aliv2.sens");
		//	std::vector<mat4f> trajectory(solverInput.numberOfImages);
		//	MLIB_CUDA_SAFE_CALL(cudaMemcpy(trajectory.data(), d_transforms, sizeof(mat4f)*trajectory.size(), cudaMemcpyDeviceToHost));
		//	sd.saveToPointCloud("debug/tmp.ply", trajectory, 0, solverInput.numberOfImages*10, 10, true);
		//	int a = 5;
		//}

		m_maxResImPairs.clear();
		if (maxResidual > GUIDED_SEARCH_MAX_RES_THRESH) {
			parameters.highResidualThresh = std::min(std::max(0.2f * maxResidual, 0.1f), 0.4f);
			collectHighResiduals(solverInput, m_solverState, m_solverExtra, parameters, m_timer);
			unsigned int highResCount;
			cutilSafeCall(cudaMemcpy(&highResCount, m_solverState.d_countHighResidual, sizeof(unsigned int), cudaMemcpyDeviceToHost));
			n = std::min(highResCount, (m_maxCorrPerImage*m_maxNumberOfImages + THREADS_PER_BLOCK - 1) / THREADS_PER_BLOCK);
			cutilSafeCall(cudaMemcpy(m_solverExtra.h_maxResidual, m_solverExtra.d_maxResidual, sizeof(float) * n, cudaMemcpyDeviceToHost));
			cutilSafeCall(cudaMemcpy(m_solverExtra.h_maxResidualIndex, m_solverExtra.d_maxResidualIndex, sizeof(int) * n, cudaMemcpyDeviceToHost));

			if (n > 1) {
				// check high residuals with previous trajectory as reference //TODO MAKE EFFICIENT
				std::vector<float4x4> transforms(solverInput.numberOfImages);
				MLIB_CUDA_SAFE_CALL(cudaMemcpy(transforms.data(), d_transforms, sizeof(float4x4)*solverInput.numberOfImages, cudaMemcpyDeviceToHost));
				std::unordered_map<vec2ui, float> residualMap; //TODO should be something better than this... 
				std::unordered_map<vec2ui, float> allCollectedResidualMap; //debugging
				std::vector<EntryJ> corrs(n);
				for (unsigned int i = 0; i < n; i++) {
					MLIB_CUDA_SAFE_CALL(cudaMemcpy(corrs.data() + i, solverInput.d_correspondences + m_solverExtra.h_maxResidualIndex[i], sizeof(EntryJ), cudaMemcpyDeviceToHost));
					const EntryJ& h_corr = corrs[i];
					vec2ui imageIndices(h_corr.imgIdx_i, h_corr.imgIdx_j);
					//compute res at previous
					if (h_corr.imgIdx_j == solverInput.numberOfImages - 1 && std::abs((int)h_corr.imgIdx_i - (int)h_corr.imgIdx_j) > 10) { //introduced by latest image
						float3 prevRes = fabs(transforms[h_corr.imgIdx_i] * h_corr.pos_i - transforms[h_corr.imgIdx_j] * h_corr.pos_j); //eval new corrs with previous trajectory
						float prevMaxRes = fmaxf(prevRes.z, fmaxf(prevRes.x, prevRes.y));
						if (prevMaxRes > 1.5f*m_solverExtra.h_maxResidual[i]) {
							auto it = residualMap.find(imageIndices);
							if (it == residualMap.end()) residualMap[imageIndices] = m_solverExtra.h_maxResidual[i];
							else it->second = std::max(m_solverExtra.h_maxResidual[i], it->second);
						}
					}
					else if (h_corr.imgIdx_j == revalidateIdx && std::abs((int)h_corr.imgIdx_i - (int)h_corr.imgIdx_j) > 10) { //introduced by latest revalidate
						auto it = residualMap.find(imageIndices);
						if (it == residualMap.end()) residualMap[imageIndices] = m_solverExtra.h_maxResidual[i];
						else it->second = std::max(m_solverExtra.h_maxResidual[i], it->second);
					}
					auto it = allCollectedResidualMap.find(imageIndices);
					if (it == allCollectedResidualMap.end()) allCollectedResidualMap[imageIndices] = m_solverExtra.h_maxResidual[i];
					else it->second = std::max(m_solverExtra.h_maxResidual[i], it->second);
				}
				if (!residualMap.empty()) { //debug print
					unsigned int rep = residualMap.begin()->first.x;
					std::cout << "rep: (" << rep << ", " << solverInput.numberOfImages - 1 << ")" << std::endl;
					for (const auto& r : residualMap) m_maxResImPairs.push_back(r.first);

					////one extra solve
					//parameters.nNonLinearIterations = 1;
					//solveBundlingStub(solverInput, m_solverState, parameters, m_solverExtra, NULL, m_timer);

					////!!!debugging
					//{
					//	static SensorData sd;
					//	if (sd.m_frames.empty()) sd.loadFromFile("../data/iclnuim/aliv2.sens");
					//	std::vector<mat4f> trajectory(solverInput.numberOfImages);
					//	MLIB_CUDA_SAFE_CALL(cudaMemcpy(trajectory.data(), d_transforms, sizeof(mat4f)*trajectory.size(), cudaMemcpyDeviceToHost));
					//	sd.saveToPointCloud("debug/tmp/" + std::to_string(solverInput.numberOfImages) + "-init.ply", trajectory, 0, solverInput.numberOfImages*10, 10, true);
					//	convertLiePosesToMatricesCU(m_solverState.d_xRot, m_solverState.d_xTrans, solverInput.numberOfImages, d_transforms, m_solverState.d_xTransformInverses);
					//	MLIB_CUDA_SAFE_CALL(cudaMemcpy(trajectory.data(), d_transforms, sizeof(mat4f)*trajectory.size(), cudaMemcpyDeviceToHost));
					//	sd.saveToPointCloud("debug/tmp/" + std::to_string(solverInput.numberOfImages) + "-opt.ply", trajectory, 0, solverInput.numberOfImages*10, 10, true);
					//	int a = 5;
					//}
					////!!!debugging
				}

				//!!!debugging
				//std::vector<std::pair<vec2ui, float>> residuals(allCollectedResidualsMap.begin(), allCollectedResidualsMap.end());
				//std::sort(residuals.begin(), residuals.end(), [](const std::pair<vec2ui, float> &left, const std::pair<vec2ui, float> &right) { //debugging only
				//	return left.second > right.second;
				//});
				//if (m_maxResImPairs.size() > 1) {
				//	std::ofstream s("debug/_logs/" + std::to_string(solverInput.numberOfImages) + "_" + std::to_string(m_maxResImPairs.front().x) + "-" + std::to_string(m_maxResImPairs.front().y) + ".txt");
				//	s << "# im pairs to remove = " << m_maxResImPairs.size() << ", res thresh = " << parameters.highResidualThresh << std::endl;
				//	for (unsigned int i = 0; i < m_maxResImPairs.size(); i++) s << m_maxResImPairs[i] << std::endl;
				//	s.close();
				//}
				//!!!debugging
			}
		}
#endif
		m_solverExtra.h_maxResidual[0] = maxResidual;
		m_solverExtra.h_maxResidualIndex[0] = maxResidualIndex;
	}
	else {
		m_solverExtra.h_maxResidual[0] = 0.0f;
		m_solverExtra.h_maxResidualIndex[0] = 0;
	}
	if (m_timer) m_timer->endEvent();
}