Skip to content
This repository was archived by the owner on Oct 6, 2023. It is now read-only.

Commit ad8b661

Browse files
committed
- Improves filepath handling
- Improves checks - Fixes multiplication calls
1 parent 4f6800c commit ad8b661

File tree

3 files changed

+67
-72
lines changed

3 files changed

+67
-72
lines changed

WSICS/Normalization/CLI.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ namespace WSICS::Normalization
124124
("hema_percentile", boost::program_options::value<float>()->default_value(0.1f), "Defines how conservative the algorithm is with its blue pixel classification.")
125125
("eosin_percentile", boost::program_options::value<float>()->default_value(0.2f), "Defines how conservative the algorithm is with its red pixel classification.")
126126
("background_threshold", boost::program_options::value<float>()->default_value(0.9f), "Defines the threshold between tissue and background pixels.")
127-
("min_ellipses", boost::program_options::value<int32_t>()->default_value(false), "Allows for a custom value for the amount of ellipses on a tile.")
127+
("min_ellipses", boost::program_options::value<int32_t>()->default_value(0), "Allows for a custom value for the amount of ellipses on a tile.")
128128
("seed,s", boost::program_options::value<uint64_t>()->default_value(1000), "Defines the seed used for random processing.");
129129
}
130130

@@ -181,9 +181,9 @@ namespace WSICS::Normalization
181181
prefix = variables["prefix"].as<std::string>();
182182
postfix = variables["postfix"].as<std::string>();
183183

184-
image_output = boost::filesystem::path(variables["image_output"].as<std::string>());
185-
lut_output = boost::filesystem::path(variables["lut_output"].as<std::string>());
186-
template_input = boost::filesystem::path(variables["template_input"].as<std::string>());
184+
image_output = boost::filesystem::path(variables["image_output"].as<std::string>());
185+
lut_output = boost::filesystem::path(variables["lut_output"].as<std::string>());
186+
template_input = boost::filesystem::path(variables["template_input"].as<std::string>());
187187
template_output = boost::filesystem::path(variables["template_output"].as<std::string>());
188188

189189
if (!image_output.empty())
@@ -211,30 +211,30 @@ namespace WSICS::Normalization
211211

212212
if (IO::Logging::LogHandler::GetInstance()->GetOutputLevel() == IO::Logging::DEBUG)
213213
{
214-
boost::filesystem::path debug_potential;
214+
boost::filesystem::path potential_debug_dir;
215215
if (!image_output.empty())
216216
{
217-
debug_potential = image_output;
217+
potential_debug_dir = image_output;
218218
}
219219
else if (!lut_output.empty())
220220
{
221-
debug_potential = lut_output;
221+
potential_debug_dir = lut_output;
222222
}
223223

224-
if (input_is_directory && !debug_potential.empty())
224+
if (input_is_directory && !potential_debug_dir.empty())
225225
{
226-
debug_dir = debug_potential.string() + "/debug";
226+
debug_dir = boost::filesystem::absolute(potential_debug_dir).string() + "/debug";
227227
}
228228
else
229229
{
230-
debug_dir = debug_potential.parent_path().string() + "/debug";
230+
debug_dir = boost::filesystem::absolute(potential_debug_dir.parent_path()).string() + "/debug";
231231
}
232232
}
233233

234234
parameters.hema_percentile = variables["hema_percentile"].as<float>();
235235
parameters.eosin_percentile = variables["eosin_percentile"].as<float>();
236236
parameters.background_threshold = variables["background_threshold"].as<float>();
237-
parameters.minimum_ellipses = variables["min_ellipses"].as<uint32_t>();
237+
parameters.minimum_ellipses = variables["min_ellipses"].as<int32_t>();
238238

239239
if (parameters.hema_percentile > 1.0f)
240240
{

WSICS/Normalization/PixelClassificationHE.cpp

Lines changed: 55 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -96,66 +96,59 @@ namespace WSICS::Normalization
9696
parameters.eosin_percentile,
9797
spacing,
9898
is_multiresolution_image));
99-
HE_Staining::HE_Classifier he_classifier;
10099

101-
if (he_masks.first.full_mask.size() == cv::Size(0, 0))
100+
if (he_masks.first.full_mask.size() != cv::Size(0, 0) &&
101+
he_masks.second.full_mask.size() != cv::Size(0, 0))
102102
{
103-
throw std::runtime_error("Unable to create Hematoxylin mask");
104-
}
105-
else if (he_masks.second.full_mask.size() == cv::Size(0, 0))
106-
{
107-
throw std::runtime_error("Unable to create Eosin mask");
108-
}
109-
110-
HE_Staining::ClassificationResults classification_results;
111-
try
112-
{
113-
classification_results = he_classifier.Classify(hsd_image, background_mask, he_masks.first, he_masks.second);
114-
}
115-
catch (const std::exception& e)
116-
{
117-
throw std::runtime_error("Unable to classify HE stained tissue.");
118-
}
119-
120-
// Wanna keep?
121-
// Randomly pick samples and Fill in Cx-Cy-D major sample vectors
122-
if (classification_results.train_and_class_data.train_data.rows >= min_training_size)
123-
{
124-
if (logging_instance->GetOutputLevel() == IO::Logging::DEBUG && !m_debug_dir_.empty())
103+
HE_Staining::HE_Classifier he_classifier;
104+
HE_Staining::ClassificationResults classification_results;
105+
try
125106
{
126-
cv::imwrite(m_debug_dir_ + "/tile_" + std::to_string(random_numbers[current_tile]) + "_classified.tif", classification_results.all_classes * 100);
127-
128-
std::vector<cv::Mat> channels;
129-
channels.push_back(he_masks.second.full_mask);
130-
channels.push_back(background_mask);
131-
channels.push_back(he_masks.first.full_mask);
132-
133-
cv::Mat classes;
134-
cv::merge(channels, classes);
135-
classes.convertTo(classes, CV_8UC1);
136-
cv::imwrite(m_debug_dir_ + "/tile_" + std::to_string(random_numbers[current_tile]) + "_classes.tif", classes * 100);
107+
classification_results = he_classifier.Classify(hsd_image, background_mask, he_masks.first, he_masks.second);
108+
}
109+
catch (const std::exception& e)
110+
{
111+
throw std::runtime_error("Unable to classify HE stained tissue.");
137112
}
138113

114+
// Wanna keep?
115+
// Randomly pick samples and Fill in Cx-Cy-D major sample vectors
116+
if (classification_results.train_and_class_data.train_data.rows >= min_training_size)
117+
{
118+
if (logging_instance->GetOutputLevel() == IO::Logging::DEBUG && !m_debug_dir_.empty())
119+
{
120+
cv::Mat classifications_scaled(classification_results.all_classes * 100);
121+
cv::imwrite(m_debug_dir_ + "/tile_" + std::to_string(random_numbers[current_tile]) + "_classified.tif", classifications_scaled);
122+
123+
std::vector<cv::Mat> channels;
124+
channels.push_back(he_masks.second.full_mask);
125+
channels.push_back(background_mask);
126+
channels.push_back(he_masks.first.full_mask);
127+
128+
cv::Mat classes;
129+
cv::merge(channels, classes);
130+
classes.convertTo(classes, CV_8UC1);
131+
classes *= 100;
132+
cv::imwrite(m_debug_dir_ + "/tile_" + std::to_string(random_numbers[current_tile]) + "_classes.tif", classes);
133+
}
134+
135+
InsertTrainingData_(hsd_image, classification_results, sample_information, total_hema_count, total_eosin_count, total_background_count, parameters.max_training_size);
136+
++selected_images_count;
137+
138+
size_t hema_count_real = total_hema_count > parameters.max_training_size * 9 / 20 ? hema_count_real = parameters.max_training_size * 9 / 20 : total_hema_count;
139+
size_t eosin_count_real = total_eosin_count > parameters.max_training_size * 9 / 20 ? eosin_count_real = parameters.max_training_size * 9 / 20 : total_eosin_count;
140+
size_t background_count_real = total_background_count > parameters.max_training_size * 1 / 10 ? background_count_real = parameters.max_training_size * 1 / 10 : total_background_count;
141+
142+
logging_instance->QueueCommandLineLogging(std::to_string(hema_count_real + eosin_count_real + background_count_real) + " training samples are filled, out of " + std::to_string(parameters.max_training_size) + " required.", IO::Logging::NORMAL);
143+
logging_instance->QueueFileLogging("Filled: " + std::to_string(hema_count_real + eosin_count_real + background_count_real) + " / " + std::to_string(parameters.max_training_size), m_log_file_id_, IO::Logging::NORMAL);
144+
logging_instance->QueueFileLogging("Hema: " + std::to_string(hema_count_real) + ", Eos: " + std::to_string(eosin_count_real) + ", BG: " + std::to_string(background_count_real), m_log_file_id_, IO::Logging::NORMAL);
145+
}
139146

140-
// TrainingSampleInformation& sample_information, const cv::Mat& cx_cy, const cv::Mat& density, const std::vector<cv::Point>& data_pixels, const size_t insertion_start, const size_t pixels_to_insert, const uint8_t class_id
141-
142-
143-
InsertTrainingData_(hsd_image, classification_results, sample_information, total_hema_count, total_eosin_count, total_background_count, parameters.max_training_size);
144-
++selected_images_count;
145-
146-
size_t hema_count_real = total_hema_count > parameters.max_training_size * 9 / 20 ? hema_count_real = parameters.max_training_size * 9 / 20 : total_hema_count;
147-
size_t eosin_count_real = total_eosin_count > parameters.max_training_size * 9 / 20 ? eosin_count_real = parameters.max_training_size * 9 / 20 : total_eosin_count;
148-
size_t background_count_real = total_background_count > parameters.max_training_size * 1 / 10 ? background_count_real = parameters.max_training_size * 1 / 10 : total_background_count;
149-
150-
logging_instance->QueueCommandLineLogging(std::to_string(hema_count_real + eosin_count_real + background_count_real) + " training sets are filled, out of " + std::to_string(parameters.max_training_size) + " required.", IO::Logging::NORMAL);
151-
logging_instance->QueueFileLogging("Filled: " + std::to_string(hema_count_real + eosin_count_real + background_count_real) + " / " + std::to_string(parameters.max_training_size), m_log_file_id_, IO::Logging::NORMAL);
152-
logging_instance->QueueFileLogging("Hema: " + std::to_string(hema_count_real) + ", Eos: " + std::to_string(eosin_count_real) + ", BG: " + std::to_string(background_count_real), m_log_file_id_, IO::Logging::NORMAL);
153-
}
154-
155-
if (total_hema_count >= parameters.max_training_size * 9 / 20 && total_eosin_count >= parameters.max_training_size * 9 / 20 && total_background_count >= parameters.max_training_size / 10)
156-
{
157-
break;
158-
}
147+
if (total_hema_count >= parameters.max_training_size * 9 / 20 && total_eosin_count >= parameters.max_training_size * 9 / 20 && total_background_count >= parameters.max_training_size / 10)
148+
{
149+
break;
150+
}
151+
}
159152
}
160153

161154
if ((total_hema_count < parameters.max_training_size * 9 / 20 || total_eosin_count < parameters.max_training_size * 9 / 20 || total_background_count < parameters.max_training_size / 10))
@@ -193,9 +186,9 @@ namespace WSICS::Normalization
193186
parameters.epoch_size = 3;
194187
parameters.count_threshold = 4;
195188

196-
int sigma = 4;
197-
int low_threshold = 45;
198-
int high_threshold = 80;
189+
int sigma = 4;
190+
int low_threshold = 45;
191+
int high_threshold = 80;
199192

200193
// Prepares the logger and a string holding potential failure messages.
201194
IO::Logging::LogHandler* logging_instance(IO::Logging::LogHandler::GetInstance());
@@ -205,11 +198,13 @@ namespace WSICS::Normalization
205198
{
206199
cv::Mat temporary_matrix;
207200
hsd_image.density.convertTo(temporary_matrix, CV_8UC1);
208-
cv::imwrite(m_debug_dir_ + "/tile_" + std::to_string(tile_id) + "_density.tif", temporary_matrix * 100);
201+
temporary_matrix *= 100;
202+
cv::imwrite(m_debug_dir_ + "/tile_" + std::to_string(tile_id) + "_density.tif", temporary_matrix);
209203

210204
HE_Staining::MaskGeneration::ApplyBlur(temporary_matrix, temporary_matrix, sigma);
211205
HE_Staining::MaskGeneration::ApplyCannyEdge(temporary_matrix, temporary_matrix, low_threshold, high_threshold);
212-
cv::imwrite(m_debug_dir_ + "/tile_" + std::to_string(tile_id) + "_binary.tif", temporary_matrix * 255);
206+
temporary_matrix *= 255;
207+
cv::imwrite(m_debug_dir_ + "/tile_" + std::to_string(tile_id) + "_binary.tif", temporary_matrix);
213208
}
214209

215210
// Attempts to detect ellispes. Applies a blur and canny edge operation on the density matrix before detecting ellipses through a randomized Hough transform.
@@ -220,7 +215,7 @@ namespace WSICS::Normalization
220215
std::pair<HE_Staining::HematoxylinMaskInformation, HE_Staining::EosinMaskInformation> mask_acquisition_results;
221216

222217
// If the min_ellipses variable has been set as positive, prefer it over a calculation.
223-
double min_detected_ellipses = min_ellipses > 0 ? hsd_image.red_density.rows * hsd_image.red_density.rows * spacing[0] * spacing[0] * (150 / 247700.0) : min_ellipses;
218+
double min_detected_ellipses = min_ellipses == 0 ? hsd_image.red_density.rows * hsd_image.red_density.rows * spacing[0] * spacing[0] * (150 / 247700.0) : min_ellipses;
224219
if (detected_ellipses.size() > min_detected_ellipses || (detected_ellipses.size() > 10 && !is_multiresolution))
225220
{
226221
logging_instance->QueueFileLogging("Passed step 1: Number of nuclei " + std::to_string(detected_ellipses.size()), m_log_file_id_, IO::Logging::NORMAL);

WSICS/Normalization/WSICS_Algorithm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ namespace WSICS::Normalization
160160
// Write sample images to Harddisk For testing
161161
//===========================================================================
162162
// Don't remove! usable for looking at samples of standardization
163-
if (!m_debug_directory_.empty() && logging_instance->GetOutputLevel() == IO::Logging::DEBUG)
163+
if (logging_instance->GetOutputLevel() == IO::Logging::DEBUG && !m_debug_directory_.empty() && normalized_lut.size() != cv::Size(0, 0))
164164
{
165165
logging_instance->QueueFileLogging("Writing sample standardized images to: " + m_debug_directory_.string(), m_log_file_id_, IO::Logging::NORMAL);
166166

0 commit comments

Comments
 (0)