double CropTransformer::ApplyRatioJitter(const double minVal, const double maxVal, std::mt19937 &rng) { assert(minVal > 0 && minVal <= maxVal); // ratio should always be > 0 switch (m_jitterType) { case RatioJitterType::None: return minVal; case RatioJitterType::UniRatio: if (minVal == maxVal) return minVal; else return UniRealT(minVal, maxVal)(rng); default: RuntimeError("Jitter type currently not implemented."); } return -1; }
void CropTransformer::Apply(cv::Mat &mat) { auto seed = GetSeed(); auto rng = m_rngs.pop_or_create( [seed]() { return std::make_unique<std::mt19937>(seed); }); double ratio = 1; switch (m_jitterType) { case RatioJitterType::None: ratio = m_cropRatioMin; break; case RatioJitterType::UniRatio: if (m_cropRatioMin == m_cropRatioMax) { ratio = m_cropRatioMin; } else { ratio = UniRealT(m_cropRatioMin, m_cropRatioMax)(*rng); assert(m_cropRatioMin <= ratio && ratio < m_cropRatioMax); } break; default: RuntimeError("Jitter type currently not implemented."); } mat = mat(GetCropRect(m_cropType, mat.rows, mat.cols, ratio, *rng)); if (m_hFlip && std::bernoulli_distribution()(*rng)) { cv::flip(mat, mat, 1); } m_rngs.push(std::move(rng)); }
cv::Rect CropTransformer::GetCropRect(CropType type, int viewIndex, int crow, int ccol, double cropRatio, std::mt19937 &rng) { assert(crow > 0); assert(ccol > 0); assert(0 < cropRatio && cropRatio <= 1.0); // Get square crop size that preserves aspect ratio. int cropSize = (int)(std::min(crow, ccol) * cropRatio); int cropSizeX = cropSize; int cropSizeY = cropSize; // Change aspect ratio, if this option is enabled. if (m_curAspectRatioRadius > 0) { double factor = 1.0 + UniRealT(-m_curAspectRatioRadius, m_curAspectRatioRadius)(rng); double area = cropSize * cropSize; double newArea = area * factor; if (std::bernoulli_distribution()(rng)) { cropSizeX = (int)std::sqrt(newArea); cropSizeY = (int)(area / cropSizeX); } else { cropSizeY = (int)std::sqrt(newArea); cropSizeX = (int)(area / cropSizeY); } // This clamping should be ok if jittering ratio is not too big. cropSizeX = std::min(cropSizeX, ccol); cropSizeY = std::min(cropSizeY, crow); } int xOff = -1; int yOff = -1; switch (type) { case CropType::Center: assert(viewIndex == 0); xOff = (ccol - cropSizeX) / 2; yOff = (crow - cropSizeY) / 2; break; case CropType::Random: assert(viewIndex == 0); xOff = UniIntT(0, ccol - cropSizeX)(rng); yOff = UniIntT(0, crow - cropSizeY)(rng); break; case CropType::MultiView10: { assert(0 <= viewIndex && viewIndex < 10); // 0 - 4: 4 corners + center crop. 5 - 9: same, but with a flip. int isubView = viewIndex % 5; switch (isubView) { // top-left case 0: xOff = 0; yOff = 0; break; // top-right case 1: xOff = ccol - cropSizeX; yOff = 0; break; // bottom-left case 2: xOff = 0; yOff = crow - cropSizeY; break; // bottom-right case 3: xOff = ccol - cropSizeX; yOff = crow - cropSizeY; break; // center case 4: xOff = (ccol - cropSizeX) / 2; yOff = (crow - cropSizeY) / 2; break; } break; } default: assert(false); } assert(0 <= xOff && xOff <= ccol - cropSizeX); assert(0 <= yOff && yOff <= crow - cropSizeY); return cv::Rect(xOff, yOff, cropSizeX, cropSizeY); }