<commit_before>#include "AutoTrace.h"

// ITK
#include "itkAndImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkConnectedThresholdImageFilter.h"
#include "itkImage.h"
#include "itkVectorIndexSelectionCastImageFilter.h"

void Trace(const RGBImageType::Pointer image, const itk::CovariantVector<unsigned char, 3>& color, const itk::Index<2>& seed)
{
  // Create a color epsilon lower than the user supplied color
  int epsilon = 10;
  RGBImageType::PixelType lowerColor;
  RGBImageType::PixelType upperColor;
  for(unsigned int component = 0; component < 3; ++component)
    {
    lowerColor[component] = std::max(static_cast<int>(color[component]) - epsilon, 0); // Truncate negative values
    upperColor[component] = std::min(static_cast<int>(color[component]) + epsilon, 255); // Truncate values above 255
    }
  std::cout << "Lower color: " << lowerColor << std::endl;
  std::cout << "Upper color: " << upperColor << std::endl;
  
  // Threshold all 3 channels and AND the result
  std::vector<ScalarImageType::Pointer> thresholdedChannels(3);
  for(unsigned int channel = 0; channel < 3; ++channel)
  {
    typedef itk::VectorIndexSelectionCastImageFilter<RGBImageType, ScalarImageType> IndexSelectionType;
    IndexSelectionType::Pointer indexSelectionFilter = IndexSelectionType::New();
    indexSelectionFilter->SetIndex(channel);
    indexSelectionFilter->SetInput(image);
    indexSelectionFilter->Update();

    // Use the color of the selection to threshold the image (looking for similar colors)
    typedef itk::BinaryThresholdImageFilter <ScalarImageType, ScalarImageType> BinaryThresholdImageFilterType;
    // Color pixels inside the threshold white. Color pixels outside the threshold black.
    BinaryThresholdImageFilterType::Pointer thresholdFilter = BinaryThresholdImageFilterType::New();
    thresholdFilter->SetInput(indexSelectionFilter->GetOutput());
    thresholdFilter->SetLowerThreshold(lowerColor[channel]);
    thresholdFilter->SetUpperThreshold(upperColor[channel]);
    thresholdFilter->SetInsideValue(200); // White
    thresholdFilter->SetOutsideValue(0); // Black
    thresholdFilter->Update();

    thresholdedChannels[channel] = ScalarImageType::New();
    DeepCopy<ScalarImageType>(thresholdFilter->GetOutput(), thresholdedChannels[channel]);
    }

  // Keep only region where all channels passed the threshold test
  typedef itk::AndImageFilter <ScalarImageType> AndImageFilterType;

  AndImageFilterType::Pointer andFilter1 = AndImageFilterType::New();
  andFilter1->SetInput(0, thresholdedChannels[0]);
  andFilter1->SetInput(1, thresholdedChannels[1]);
  andFilter1->Update();

  AndImageFilterType::Pointer andFilter2 = AndImageFilterType::New();
  andFilter2->SetInput(0, andFilter1->GetOutput());
  andFilter2->SetInput(1, thresholdedChannels[2]);
  andFilter2->Update();

  WriteImage<ScalarImageType>(andFilter2->GetOutput(), "Thresholded.png");
  
  // Use the location of the selection to get pixels that fit the color criterion and that are connected to the selected point.
  typedef itk::ConnectedThresholdImageFilter<ScalarImageType, ScalarImageType> ConnectedFilterType;
  ConnectedFilterType::Pointer connectedThreshold = ConnectedFilterType::New();
  connectedThreshold->SetLower(180);
  connectedThreshold->SetUpper(220);
  connectedThreshold->SetReplaceValue(255);
  connectedThreshold->SetSeed(seed);
  connectedThreshold->SetInput(andFilter2->GetOutput());
  connectedThreshold->Update();

  WriteImage<ScalarImageType>(connectedThreshold->GetOutput(), "connectedThreshold.png");
}<commit_msg>Dilate thresholded image to fill potential holes.<commit_after>#include "AutoTrace.h"

// ITK
#include "itkAndImageFilter.h"
#include "itkBinaryBallStructuringElement.h"
#include "itkBinaryDilateImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkConnectedThresholdImageFilter.h"
#include "itkImage.h"
#include "itkVectorIndexSelectionCastImageFilter.h"

void Trace(const RGBImageType::Pointer image, const itk::CovariantVector<unsigned char, 3>& color, const itk::Index<2>& seed)
{
  // Create a color epsilon lower than the user supplied color
  int epsilon = 10;
  RGBImageType::PixelType lowerColor;
  RGBImageType::PixelType upperColor;
  for(unsigned int component = 0; component < 3; ++component)
    {
    lowerColor[component] = std::max(static_cast<int>(color[component]) - epsilon, 0); // Truncate negative values
    upperColor[component] = std::min(static_cast<int>(color[component]) + epsilon, 255); // Truncate values above 255
    }
  std::cout << "Lower color: ";
  for(unsigned int i = 0; i < 3; ++i)
    {
    std::cout << static_cast<int>(lowerColor[i]) << " ";
    }
  std::cout << std::endl;
  
  std::cout << "Upper color: ";
  for(unsigned int i = 0; i < 3; ++i)
    {
    std::cout << static_cast<int>(upperColor[i]) << " ";
    }
  std::cout << std::endl;
  // Threshold all 3 channels and AND the result
  std::vector<ScalarImageType::Pointer> thresholdedChannels(3);
  for(unsigned int channel = 0; channel < 3; ++channel)
  {
    typedef itk::VectorIndexSelectionCastImageFilter<RGBImageType, ScalarImageType> IndexSelectionType;
    IndexSelectionType::Pointer indexSelectionFilter = IndexSelectionType::New();
    indexSelectionFilter->SetIndex(channel);
    indexSelectionFilter->SetInput(image);
    indexSelectionFilter->Update();

    // Use the color of the selection to threshold the image (looking for similar colors)
    typedef itk::BinaryThresholdImageFilter <ScalarImageType, ScalarImageType> BinaryThresholdImageFilterType;
    // Color pixels inside the threshold white. Color pixels outside the threshold black.
    BinaryThresholdImageFilterType::Pointer thresholdFilter = BinaryThresholdImageFilterType::New();
    thresholdFilter->SetInput(indexSelectionFilter->GetOutput());
    thresholdFilter->SetLowerThreshold(lowerColor[channel]);
    thresholdFilter->SetUpperThreshold(upperColor[channel]);
    thresholdFilter->SetInsideValue(255); // White
    thresholdFilter->SetOutsideValue(0); // Black
    thresholdFilter->Update();

    thresholdedChannels[channel] = ScalarImageType::New();
    DeepCopy<ScalarImageType>(thresholdFilter->GetOutput(), thresholdedChannels[channel]);
    }

  // Keep only region where all channels passed the threshold test
  typedef itk::AndImageFilter <ScalarImageType> AndImageFilterType;

  AndImageFilterType::Pointer andFilter1 = AndImageFilterType::New();
  andFilter1->SetInput(0, thresholdedChannels[0]);
  andFilter1->SetInput(1, thresholdedChannels[1]);
  andFilter1->Update();

  AndImageFilterType::Pointer andFilter2 = AndImageFilterType::New();
  andFilter2->SetInput(0, andFilter1->GetOutput());
  andFilter2->SetInput(1, thresholdedChannels[2]);
  andFilter2->Update();

  ScalarImageType::Pointer thresholdedImage = ScalarImageType::New();
  DeepCopy<ScalarImageType>(andFilter2->GetOutput(), thresholdedImage);
  WriteImage<ScalarImageType>(thresholdedImage, "Thresholded.png");
  
  // Dilate the image.
  typedef itk::BinaryBallStructuringElement<ScalarImageType::PixelType, 2> StructuringElementType;
  StructuringElementType structuringElement;
  unsigned int radius = 5; // How big of holes we want to connect.
  structuringElement.SetRadius(radius);
  structuringElement.CreateStructuringElement();
 
  typedef itk::BinaryDilateImageFilter <ScalarImageType, ScalarImageType, StructuringElementType> BinaryDilateImageFilterType;
  BinaryDilateImageFilterType::Pointer dilateFilter = BinaryDilateImageFilterType::New();
  dilateFilter->SetInput(thresholdedImage);
  dilateFilter->SetKernel(structuringElement);
  dilateFilter->SetDilateValue(255);
  dilateFilter->Update();
  
  ScalarImageType::Pointer dilatedImage = ScalarImageType::New();
  DeepCopy<ScalarImageType>(dilateFilter->GetOutput(), dilatedImage);
  WriteImage<ScalarImageType>(dilatedImage, "Dilated.png");
  
  // Get pixels that are connected to the selected point.
  typedef itk::ConnectedThresholdImageFilter<ScalarImageType, ScalarImageType> ConnectedFilterType;
  ConnectedFilterType::Pointer connectedThreshold = ConnectedFilterType::New();
  connectedThreshold->SetLower(255);
  connectedThreshold->SetUpper(255);
  connectedThreshold->SetReplaceValue(255);
  connectedThreshold->SetSeed(seed);
  connectedThreshold->SetInput(dilatedImage);
  connectedThreshold->Update();

  WriteImage<ScalarImageType>(connectedThreshold->GetOutput(), "connectedThreshold.png");
}
{'fraction_non_alphanumeric': 0.11594546532305869, 'fraction_numerical': 0.012329579134558387, 'mean_word_length': 6.4, 'pattern_counts': {'":': 0, '<': 68, '<?xml version=': 0, '>': 92, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '598115', 'n_tokens_mistral': 2433, 'n_tokens_neox': 2320, 'n_words': 495}