11#include < FAST/Data/ImagePyramid.hpp>
22#include < FAST/Data/Image.hpp>
3+ #include < FAST/Algorithms/ImageResizer/ImageResizer.hpp>
34#include " PatchGenerator.hpp"
45
56namespace fast {
@@ -20,13 +21,13 @@ PatchGenerator::PatchGenerator() {
2021
2122 createIntegerAttribute (" patch-size" , " Patch size" , " " , 0 );
2223 createIntegerAttribute (" patch-level" , " Patch level" , " Patch level used for image pyramid inputs" , m_level);
23- createIntegerAttribute (" patch-magnification" , " Patch magnification" , " Patch magnification to be used for image pyramid inputs" , m_magnification);
24+ createFloatAttribute (" patch-magnification" , " Patch magnification" , " Patch magnification to be used for image pyramid inputs" , m_magnification);
2425 createFloatAttribute (" patch-overlap" , " Patch overlap" , " Patch overlap in percent" , m_overlapPercent);
2526 createFloatAttribute (" mask-threshold" , " Mask threshold" , " Threshold, in percent, for how much of the candidate patch must be inside the mask to be accepted" , m_maskThreshold);
2627 createIntegerAttribute (" padding-value" , " Padding value" , " Value to pad patches with when out-of-bounds. Default is negative, meaning it will use (white)255 for color images, and (black)0 for grayscale images" , m_paddingValue);
2728}
2829
29- PatchGenerator::PatchGenerator (int width, int height, int depth, int level, int magnification, float percent, float maskThreshold, int paddingValue) : PatchGenerator() {
30+ PatchGenerator::PatchGenerator (int width, int height, int depth, int level, float magnification, float percent, float maskThreshold, int paddingValue) : PatchGenerator() {
3031 setPatchSize (width, height, depth);
3132 setPatchLevel (level);
3233 setOverlap (percent);
@@ -82,9 +83,34 @@ void PatchGenerator::generateStream() {
8283 throw Exception (" Patch size must be dividable by 2" );
8384
8485 int level = m_level;
86+ float resampleFactor = 1 .0f ;
8587 if (m_magnification > 0 ) {
86- level = m_inputImagePyramid->getLevelForMagnification (m_magnification);
87- reportInfo () << " Choose level " << level << " for image pyramid for magnification " << m_magnification << reportEnd ();
88+ try {
89+ level = m_inputImagePyramid->getLevelForMagnification (m_magnification);
90+ reportInfo () << " Choose level " << level << " for image pyramid for magnification " << m_magnification << reportEnd ();
91+ } catch (Exception &e) {
92+ // Magnification level not available
93+ // Have to sample for a higher level if possible
94+ reportWarning () << " Requested magnification level does not exist in image pyramid. " <<
95+ " Will now try to sample from a lower level and resize. This may increase runtime." << reportEnd ();
96+ // First find level which is larger than request magnification
97+ float targetSpacing = 0 .00025f * (40 .0f / (float )m_magnification);
98+ level = 0 ;
99+ float level0spacing = m_inputImagePyramid->getSpacing ().x ();
100+ for (int i = 0 ; i < m_inputImagePyramid->getNrOfLevels (); ++i) {
101+ float levelSpacing = m_inputImagePyramid->getLevelScale (i)*level0spacing;
102+ level = i;
103+ resampleFactor = targetSpacing / levelSpacing; // Scale between level and the magnification level we want
104+ if (i+1 < m_inputImagePyramid->getNrOfLevels () &&
105+ m_inputImagePyramid->getLevelScale (i+1 )*level0spacing > targetSpacing) {
106+ break ;
107+ }
108+ }
109+ if (level < 0 )
110+ throw Exception (" Unable to generate patches for magnification level " +
111+ std::to_string (m_magnification) + " because level 0 was at a lower magnification " );
112+ reportInfo () << " Sampling patches from level " << level << " and using a resampling factor of " << resampleFactor << reportEnd ();
113+ }
88114 }
89115
90116 const int levelWidth = m_inputImagePyramid->getLevelWidth (level);
@@ -106,19 +132,19 @@ void PatchGenerator::generateStream() {
106132 for (int patchY = 0 ; patchY < patchesY; ++patchY) {
107133 for (int patchX = 0 ; patchX < patchesX; ++patchX) {
108134 mRuntimeManager ->startRegularTimer (" create patch" );
109- int patchWidth = m_width;
110- if (patchX*patchWidthWithoutOverlap + patchWidth - overlapInPixelsX >= levelWidth) {
111- patchWidth = levelWidth - patchX * patchWidthWithoutOverlap + overlapInPixelsX;
135+ int patchWidth = m_width*resampleFactor ;
136+ if (patchWidth + ( patchX*patchWidthWithoutOverlap - overlapInPixelsX)*resampleFactor >= levelWidth) {
137+ patchWidth = levelWidth - ( patchX * patchWidthWithoutOverlap - overlapInPixelsX)*resampleFactor ;
112138 }
113- int patchHeight = m_height;
114- if (patchY*patchHeightWithoutOverlap + patchHeight - overlapInPixelsY >= levelHeight) {
115- patchHeight = levelHeight - patchY * patchHeightWithoutOverlap + overlapInPixelsY;
139+ int patchHeight = m_height*resampleFactor ;
140+ if (patchHeight + ( patchY*patchHeightWithoutOverlap - overlapInPixelsY)*resampleFactor >= levelHeight) {
141+ patchHeight = levelHeight - ( patchY * patchHeightWithoutOverlap - overlapInPixelsY)*resampleFactor ;
116142 }
117- int patchOffsetX = patchX * patchWidthWithoutOverlap - overlapInPixelsX;
143+ int patchOffsetX = ( patchX * patchWidthWithoutOverlap - overlapInPixelsX)*resampleFactor ;
118144 if (patchX == 0 && overlapInPixelsX > 0 ) {
119145 patchOffsetX = 0 ;
120146 }
121- int patchOffsetY = patchY * patchHeightWithoutOverlap - overlapInPixelsY;
147+ int patchOffsetY = ( patchY * patchHeightWithoutOverlap - overlapInPixelsY)*resampleFactor ;
122148 if (patchY == 0 && overlapInPixelsY > 0 ) {
123149 patchOffsetY = 0 ;
124150 }
@@ -165,8 +191,12 @@ void PatchGenerator::generateStream() {
165191 paddingValue = 0 ;
166192 }
167193 }
168- if (patch->getWidth () != m_width || patch->getHeight () != m_height) {
169- patch = patch->crop (Vector2i (0 , 0 ), Vector2i (m_width, m_height), true , paddingValue);
194+ if (patch->getWidth () != (int )(m_width*resampleFactor) || patch->getHeight () != (int )(m_height*resampleFactor)) {
195+ // Edge cases, patches may not be the target patch size. Need to pad.
196+ patch = patch->crop (Vector2i (0 , 0 ), Vector2i (m_width*resampleFactor, m_height*resampleFactor), true , paddingValue);
197+ }
198+ if (resampleFactor > 1 .0f ) {
199+ patch = ImageResizer::create (m_width, m_height)->connect (patch)->runAndGetOutputData <Image>();
170200 }
171201 if (m_overlapPercent > 0 .0f && (patchX == 0 || patchY == 0 )) {
172202 int offsetX = patchX == 0 ? -overlapInPixelsX : 0 ;
@@ -369,7 +399,7 @@ void PatchGenerator::setPaddingValue(int paddingValue) {
369399 setModified (true );
370400}
371401
372- void PatchGenerator::setPatchMagnification (int magnification) {
402+ void PatchGenerator::setPatchMagnification (float magnification) {
373403 m_magnification = magnification;
374404 setModified (true );
375405}
0 commit comments