| 168 | } |
| 169 | |
| 170 | static void medianCut( const Array2D &luminance, const Array2D &summedLuminance, MedianCutSampler::Projection projection, const Box2i &area, vector<Box2i> &areas, vector<V2f> ¢roids, int depth, int maxDepth ) |
| 171 | { |
| 172 | float radiansPerPixel = M_PI / (luminance.shape()[1]); |
| 173 | |
| 174 | if( depth==maxDepth ) |
| 175 | { |
| 176 | float totalEnergy = 0.0f; |
| 177 | V2f position( 0.0f ); |
| 178 | for( int y=area.min.y; y<=area.max.y; y++ ) |
| 179 | { |
| 180 | for( int x=area.min.x; x<=area.max.x; x++ ) |
| 181 | { |
| 182 | float e = luminance[x][y]; |
| 183 | position += V2f( x, y ) * e; |
| 184 | totalEnergy += e; |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | position /= totalEnergy; |
| 189 | centroids.push_back( position ); |
| 190 | areas.push_back( area ); |
| 191 | } |
| 192 | else |
| 193 | { |
| 194 | // find cut dimension |
| 195 | V2f size = area.size(); |
| 196 | if( projection==MedianCutSampler::LatLong ) |
| 197 | { |
| 198 | float centreY = (area.max.y + area.min.y) / 2.0f; |
| 199 | float centreAngle = (M_PI - radiansPerPixel) / 2.0f - centreY * radiansPerPixel; |
| 200 | size.x *= cosf( centreAngle ); |
| 201 | } |
| 202 | int cutAxis = size.x > size.y ? 0 : 1; |
| 203 | float e = energy( summedLuminance, area ); |
| 204 | float halfE = e / 2.0f; |
| 205 | Box2i lowArea = area; |
| 206 | while( e > halfE ) |
| 207 | { |
| 208 | lowArea.max[cutAxis] -= 1; |
| 209 | e = energy( summedLuminance, lowArea ); |
| 210 | } |
| 211 | Box2i highArea = area; |
| 212 | highArea.min[cutAxis] = lowArea.max[cutAxis] + 1; |
| 213 | medianCut( luminance, summedLuminance, projection, lowArea, areas, centroids, depth + 1, maxDepth ); |
| 214 | medianCut( luminance, summedLuminance, projection, highArea, areas, centroids, depth + 1, maxDepth ); |
| 215 | } |
| 216 | } |
| 217 | |
| 218 | |
| 219 | ObjectPtr MedianCutSampler::doOperation( const CompoundObject * operands ) |
no test coverage detected