bool DistanceTransformWholeSlideFilter::process() const { std::vector<unsigned long long> dims = this->_input->getLevelDimensions(this->_processedLevel); double downsample = this->_input->getLevelDownsample(this->_processedLevel); MultiResolutionImageWriter writer; writer.setColorType(pathology::ColorType::Monochrome); writer.setCompression(pathology::Compression::LZW); writer.setDataType(pathology::DataType::UInt32); writer.setInterpolation(pathology::Interpolation::NearestNeighbor); writer.setTileSize(512); std::vector<double> spacing = _input->getSpacing(); if (!spacing.empty()) { spacing[0] *= downsample; spacing[1] *= downsample; writer.setSpacing(spacing); } writer.setProgressMonitor(_monitor); std::string firstPassFile = _outPath; std::string basename = core::extractBaseName(_outPath); core::changeBaseName(firstPassFile, basename + "_firstpass"); unsigned int* buffer_t_x = new unsigned int[512]; unsigned int* buffer_t_y = new unsigned int[512 * dims[0]]; unsigned char* tile = new unsigned char[512 * 512]; unsigned int* out_tile = new unsigned int[512 * 512]; unsigned int maxDist = (dims[0] + dims[1] / 2) + 1; std::fill(out_tile, out_tile + 512 * 512, maxDist); std::fill(buffer_t_x, buffer_t_x + 512, maxDist); std::fill(buffer_t_y, buffer_t_y + 512 * dims[0], maxDist); if (writer.openFile(firstPassFile) != 0) { std::cerr << "ERROR: Could not open file for writing" << std::endl; return false; } writer.writeImageInformation(dims[0], dims[1]); // Forward pass for (unsigned long long t_y = 0; t_y < dims[1]; t_y += 512) { std::fill(buffer_t_x, buffer_t_x + 512, maxDist); for (unsigned long long t_x = 0; t_x < dims[0]; t_x += 512) { this->_input->getRawRegion<unsigned char>(static_cast<unsigned long long>(t_x*downsample), static_cast<unsigned long long>(t_y*downsample), 512, 512, this->_processedLevel, tile); std::fill(out_tile, out_tile + 512 * 512, (dims[0] + dims[1] / 2) + 1); int startX = 0; int startY = 0; if (t_x == 0) { startX = 1; } if (t_y == 0) { startY = 1; } for (int y = startY; y < 512; ++y) { for (int x = startX; x < 512; ++x) { unsigned int curPos = y * 512 + x; unsigned char curVal = tile[curPos]; if (curVal == 1) { out_tile[curPos] = 0; } else { unsigned int upVal; if (y == 0) { upVal = buffer_t_y[t_x + x]; } else { upVal = out_tile[curPos - 512]; } unsigned int leftVal; if (x == 0) { leftVal = buffer_t_x[y]; } else { leftVal = out_tile[curPos - 1]; } unsigned int newDist = std::min(upVal, leftVal) + 1; if (newDist < maxDist) { out_tile[curPos] = newDist; } } if (x == 511) { buffer_t_x[y] = out_tile[y * 512 + x]; } if (y == 511) { buffer_t_y[t_x + x] = out_tile[y * 512 + x]; } } } writer.writeBaseImagePart(reinterpret_cast<void*>(out_tile)); } } std::fill(buffer_t_y, buffer_t_y + 512 * dims[0], maxDist); writer.finishImage(); // Backward pass MultiResolutionImageReader reader = MultiResolutionImageReader(); MultiResolutionImage* firstPass = reader.open(firstPassFile); if (writer.openFile(_outPath) != 0) { std::cerr << "ERROR: Could not open file for writing" << std::endl; return false; } writer.setProgressMonitor(_monitor); writer.writeImageInformation(dims[0], dims[1]); long long start_t_y = std::ceil(dims[1] / 512.)*512 - 512; long long start_t_x = std::ceil(dims[0] / 512.)*512 - 512; for (long long t_y = start_t_y; t_y >= 0; t_y -= 512) { std::fill(buffer_t_x, buffer_t_x + 512, maxDist); for (long long t_x = start_t_x; t_x >= 0; t_x -= 512) { firstPass->getRawRegion<unsigned int>(static_cast<unsigned long long>(t_x*downsample), static_cast<unsigned long long>(t_y*downsample), 512, 512, 0, out_tile); int startX = 511; int startY = 511; for (int y = 511; y >= 0; --y) { for (int x = 511; x >= 0; --x) { unsigned int curPos = y * 512 + x; unsigned int downVal; if (t_y + y + 1 >= dims[1]) { downVal = maxDist; } else if (y == 511) { downVal = buffer_t_y[t_x + x]; } else { downVal = out_tile[curPos + 512]; } unsigned int rightVal; if (t_x + x + 1 >= dims[0]) { rightVal = maxDist; } else if (x == 511) { rightVal = buffer_t_x[y]; } else { rightVal = out_tile[curPos + 1]; } unsigned int newDist = std::min(downVal, rightVal) + 1; if (newDist < out_tile[curPos]) { out_tile[curPos] = newDist; } if (x == 0) { buffer_t_x[y] = out_tile[y * 512 + x]; } if (y == 0) { buffer_t_y[t_x + x] = out_tile[y * 512 + x]; } } } writer.writeBaseImagePartToLocation(reinterpret_cast<void*>(out_tile), t_x, t_y); } } std::fill(buffer_t_y, buffer_t_y + 512 * dims[0], maxDist); writer.finishImage(); delete firstPass; delete[] buffer_t_x; delete[] buffer_t_y; delete[] tile; delete[] out_tile; core::deleteFile(firstPassFile); return true; }
void AnnotationToMask::convert(const std::shared_ptr<AnnotationList>& annotationList, const std::string& maskFile, const std::vector<unsigned long long>& dimensions, const std::vector<double>& spacing, const std::map<std::string, int> nameToLabel, const std::vector<std::string> nameOrder) const { bool hasGroups = !annotationList->getGroups().empty(); std::vector<std::shared_ptr<Annotation> > annotations = annotationList->getAnnotations(); for (auto annotation = annotations.begin(); annotation != annotations.end(); ++annotation) { if (!(*annotation)->isClockwise()) { std::vector<Point> coords = (*annotation)->getCoordinates(); std::reverse(coords.begin(), coords.end()); (*annotation)->setCoordinates(coords); } } if (!nameOrder.empty() && !nameToLabel.empty()) { std::vector<std::shared_ptr<Annotation> > unorderedAnnotations = annotations; annotations.clear(); for (unsigned int i = 0; i < nameOrder.size(); ++i) { std::string currentName = nameOrder[i]; for (std::vector<std::shared_ptr<Annotation> >::iterator it = unorderedAnnotations.begin(); it != unorderedAnnotations.end(); ++it) { bool matchesName = false; if (hasGroups) { if ((*it)->getGroup()) { if ((*it)->getGroup()->getName() == currentName) { matchesName = true; } } } else { if ((*it)->getName() == currentName) { matchesName = true; } } if (matchesName) { annotations.push_back((*it)); } } } } MultiResolutionImageWriter writer; if (_monitor) { writer.setProgressMonitor(_monitor); } if (writer.openFile(maskFile) == 0) { writer.setColorType(pathology::Monochrome); writer.setCompression(pathology::LZW); writer.setTileSize(512); writer.setDataType(pathology::UChar); writer.setInterpolation(pathology::NearestNeighbor); std::vector<double> spacing_copy(spacing); writer.setSpacing(spacing_copy); writer.writeImageInformation(dimensions[0], dimensions[1]); unsigned char* buffer = new unsigned char[512 * 512]; for (unsigned long long ty = 0; ty < dimensions[1]; ty += 512) { for (unsigned long long tx = 0; tx < dimensions[0]; tx += 512) { std::fill(buffer, buffer + 512 * 512, 0); for (std::vector<std::shared_ptr<Annotation> >::const_iterator annotation = annotations.begin(); annotation != annotations.end(); ++annotation) { if (!nameToLabel.empty() && !(*annotation)->getGroup() && hasGroups) { continue; } std::string nm = (*annotation)->getName(); std::vector<Point> coords = (*annotation)->getCoordinates(); std::vector<Point> bbox = (*annotation)->getImageBoundingBox(); if (!coords.empty()) { coords.push_back(coords[0]); } int label = 1; if (!nameToLabel.empty()) { std::map<std::string, int>::const_iterator it; if (hasGroups) { it = nameToLabel.find((*annotation)->getGroup()->getName()); } else { it = nameToLabel.find(nm); } if (it != nameToLabel.end()) { label = it->second; } else { label = 0; } } for (unsigned int y = 0; y < 512; ++y) { if (ty + y >= dimensions[1]) { break; } if (ty + y > bbox[0].getY() && ty + y < bbox[1].getY()) { for (unsigned int x = 0; x < 512; ++x) { if (tx + x > bbox[0].getX() && tx + x < bbox[1].getX()) { if (tx + x >= dimensions[0]) { break; } int in_poly = wn_PnPoly(Point(static_cast<float>(tx + x), static_cast<float>(ty + y)), coords) != 0 ? 1 : 0; if (nameOrder.empty()) { buffer[y * 512 + x] = in_poly * label > buffer[y * 512 + x] ? in_poly * label : buffer[y * 512 + x]; } else if (in_poly) { buffer[y * 512 + x] = in_poly * label; } } } } } } writer.writeBaseImagePart((void*)buffer); } } writer.finishImage(); delete[] buffer; } }
bool ThresholdWholeSlideFilter::process() { std::vector<unsigned long long> dims = this->_input->getLevelDimensions(this->_processedLevel); double downsample = this->_input->getLevelDownsample(this->_processedLevel); MultiResolutionImageWriter writer; unsigned int outSamplesPerPixel = _input->getSamplesPerPixel(); unsigned int inSamplesPerPixel = _input->getSamplesPerPixel(); if (_component >= inSamplesPerPixel) { std::cerr << "ERROR: Selected component is larger than number of input components, fallback to all components" << std::endl; _component = -1; } if (_component >= 0 || _input->getSamplesPerPixel() == 1) { writer.setColorType(pathology::ColorType::Monochrome); outSamplesPerPixel = 1; } else { writer.setColorType(pathology::ColorType::Indexed); writer.setNumberOfIndexedColors(_input->getSamplesPerPixel()); } writer.setCompression(pathology::Compression::LZW); writer.setDataType(pathology::DataType::UChar); writer.setInterpolation(pathology::Interpolation::NearestNeighbor); writer.setTileSize(512); std::vector<double> spacing = _input->getSpacing(); if (!spacing.empty()) { spacing[0] *= downsample; spacing[1] *= downsample; writer.setSpacing(spacing); } if (writer.openFile(_outPath) != 0) { std::cerr << "ERROR: Could not open file for writing" << std::endl; return false; } writer.setProgressMonitor(_monitor); writer.writeImageInformation(dims[0], dims[1]); float* tile = new float[512 * 512 * _input->getSamplesPerPixel()]; unsigned char* out_tile = new unsigned char[512 * 512 * outSamplesPerPixel]; for (unsigned long long t_y = 0; t_y < dims[1]; t_y += 512) { for (unsigned long long t_x = 0; t_x < dims[0]; t_x += 512) { this->_input->getRawRegion<float>(static_cast<unsigned long long>(t_x*downsample), static_cast<unsigned long long>(t_y*downsample), 512, 512, this->_processedLevel, tile); for (unsigned int y = 0; y < 512; ++y) { for (unsigned int x = 0; x < 512; ++x) { for (unsigned int c = 0; c < _input->getSamplesPerPixel(); ++c) { if (c == _component) { float curVal = tile[y * 512 * inSamplesPerPixel + x * inSamplesPerPixel + c]; if (curVal >= _lowerThreshold && curVal < _upperThreshold) { out_tile[y * 512 + x] = 1; } else { out_tile[y * 512 + x] = 0; } } else if (_component < 0) { float curVal = tile[y * 512 * inSamplesPerPixel + x * inSamplesPerPixel + c]; if (curVal >= _lowerThreshold && curVal < _upperThreshold) { out_tile[y * 512 * inSamplesPerPixel + x * inSamplesPerPixel + c] = 1; } else { out_tile[y * 512 * inSamplesPerPixel + x * inSamplesPerPixel + c] = 0; } } } } } writer.writeBaseImagePart(reinterpret_cast<void*>(out_tile)); } } writer.finishImage(); delete[] tile; delete[] out_tile; return true; }
bool ArithmeticWholeSlideFilter::process() { std::vector<unsigned long long> dims = this->_input->getLevelDimensions(this->_processedLevel); double downsample = this->_input->getLevelDownsample(this->_processedLevel); MultiResolutionImageWriter writer; writer.setColorType(pathology::ColorType::Monochrome); writer.setCompression(pathology::Compression::LZW); writer.setDataType(pathology::DataType::UInt32); writer.setInterpolation(pathology::Interpolation::NearestNeighbor); writer.setTileSize(512); std::vector<double> spacing = _input->getSpacing(); if (!spacing.empty()) { spacing[0] *= downsample; spacing[1] *= downsample; writer.setSpacing(spacing); } if (writer.openFile(_outPath) != 0) { std::cerr << "ERROR: Could not open file for writing" << std::endl; return false; } writer.setProgressMonitor(_monitor); writer.writeImageInformation(dims[0], dims[1]); std::vector<unsigned char> labels; std::vector<std::string> stringLabels; core::split(_expression, stringLabels, ","); labels.resize(core::fromstring<unsigned int>(stringLabels.back()), 0); for (unsigned int i = 0; i < stringLabels.size() - 1; ++i) { labels[core::fromstring<unsigned int>(stringLabels[i])] = 1; } unsigned int* tile = new unsigned int[512 * 512]; unsigned int* out_tile = new unsigned int[512 * 512]; for (unsigned long long t_y = 0; t_y < dims[1]; t_y += 512) { for (unsigned long long t_x = 0; t_x < dims[0]; t_x += 512) { this->_input->getRawRegion<unsigned int>(static_cast<unsigned long long>(t_x*downsample), static_cast<unsigned long long>(t_y*downsample), 512, 512, this->_processedLevel, tile); for (unsigned int y = 0; y < 512; ++y) { for (unsigned int x = 0; x < 512; ++x) { float curVal = tile[y * 512 + x]; if (curVal > 0 && labels[curVal]==0) { out_tile[y * 512 + x] = curVal; } else { out_tile[y * 512 + x] = 0; } } } writer.writeBaseImagePart(reinterpret_cast<void*>(out_tile)); } } writer.finishImage(); delete[] tile; delete[] out_tile; return true; }
void convertImage(std::string fileIn, std::string fileOut, bool svs = false, std::string compression = "LZW", double quality = 70., double spacingX = -1.0, double spacingY = -1.0, unsigned int tileSize = 512) { MultiResolutionImageReader read; MultiResolutionImageWriter* writer; if (svs) { writer = new AperioSVSWriter(); } else { writer = new MultiResolutionImageWriter(); } if (core::fileExists(fileIn)) { MultiResolutionImage* img = read.open(fileIn); if (img) { if (img->valid()) { writer->setTileSize(tileSize); if (compression == string("LZW")) { writer->setCompression(LZW); } else if (compression == string("RAW")) { writer->setCompression(RAW); } else if (compression == string("JPEG")) { writer->setCompression(JPEG); } else if (compression == string("JPEG2000")) { writer->setCompression(JPEG2000); } else { cout << "Invalid compression, setting default LZW as compression" << endl; writer->setCompression(LZW); } if (quality > 100) { cout << "Too high rate, maximum is 100, setting to 100 (for JPEG2000 this is equal to lossless)" << endl; writer->setJPEGQuality(100); } else if (quality <= 0.001) { cout << "Too low rate, minimum is 0.001, setting to 1" << endl; writer->setJPEGQuality(1); } else { writer->setJPEGQuality(quality); } if (spacingX > 0.0 && spacingY > 0.0) { std::vector<double> overrideSpacing; overrideSpacing.push_back(spacingX); overrideSpacing.push_back(spacingY); writer->setOverrideSpacing(overrideSpacing); } CmdLineProgressMonitor* monitor = new CmdLineProgressMonitor(); monitor->setStatus("Processing " + fileIn); writer->setProgressMonitor(monitor); writer->writeImageToFile(img, fileOut); delete monitor; } else { cout << "Input file not valid" << endl; } } else { cout << "Input file not compatible" << endl; } } else { cout << "Input file does not exist" << endl; } }