void OpenCVPicture::jiggleFit(
    RNG &rng, int subsetSize,
    float minFill) { // subsetSize==spatialSize for codifyInputData
  assert(minFill > 0);
  int fitCtr = 100; // Give up after 100 failed attempts to find a good fit
  bool goodFit = false;
  float *matData = ((float *)(mat.data));
  while (!goodFit and fitCtr-- > 0) {
    xOffset = -rng.randint(mat.cols - subsetSize / 3);
    yOffset = -rng.randint(mat.rows - subsetSize / 3);
    int pointsCtr = 0;
    int interestingPointsCtr = 0;
    for (int X = 5; X < subsetSize; X += 10) {
      for (int Y = 5; Y < subsetSize - X; Y += 10) {
        int x = X - xOffset - subsetSize / 3;
        int y = Y - yOffset - subsetSize / 3;
        pointsCtr++;
        if (0 <= x and x < mat.cols and 0 <= y and y < mat.rows) {
          interestingPointsCtr +=
              (matData[(pointsCtr % mat.channels()) + x * mat.channels() +
                       y * mat.channels() * mat.cols] != backgroundColor);
        }
      }
    }
    if (interestingPointsCtr > pointsCtr * minFill)
      goodFit = true;
  }
  if (!goodFit) {
    std::cout << filename << " " << std::flush;
    xOffset = -mat.cols / 2 - 16 + rng.randint(33);
    yOffset = -mat.rows / 2 - 16 + rng.randint(33);
  }
}
void OpenCVPicture::jiggleFit(RNG &rng, int subsetSize, float minFill) {
    for (int fitCtr = 100; // Give up after 100 failed attempts to find a good fit
            fitCtr > 0; fitCtr--) {
        {
            if (mat.cols >= subsetSize)
                xOffset = -rng.randint(mat.cols - subsetSize + 1) - subsetSize / 2;
            else
                xOffset = rng.randint(subsetSize - mat.cols + 1) - subsetSize / 2;
            if (mat.rows >= subsetSize)
                yOffset = -rng.randint(mat.rows - subsetSize + 1) - subsetSize / 2;
            else
                yOffset = rng.randint(subsetSize - mat.rows + 1) - subsetSize / 2;
        }
        if (minFill < 0) {
            fitCtr = -1; // Just take any old crop
        } else {
            int pointsCtr = 0;
            int interestingPointsCtr = 0;
            // If x0<=x<x1 and y0<=y<y1 then the (x,y)-th pixel is in the CNN's visual
            // field.
            int x0 = std::max(0, -xOffset - subsetSize / 2);
            int x1 = std::min(mat.cols, subsetSize - xOffset - subsetSize / 2);
            int y0 = std::max(0, -yOffset - subsetSize / 2);
            int y1 = std::min(mat.rows, subsetSize - yOffset - subsetSize / 2);
            float *matData = ((float *)(mat.data));
            assert(subsetSize > 20);
            int subsample = subsetSize / 20;
            for (int x = x0 + subsample / 2; x < x1; x += subsample) {
                for (int y = y0 + subsample / 2; y < y1; y += subsample) {
                    pointsCtr++;
                    int j = x * mat.channels() + y * mat.channels() * mat.cols;
                    for (int i = 0; i < mat.channels(); i++)
                        if (std::abs(matData[i + j] - backgroundColor) > 2) {
                            interestingPointsCtr++;
                            break;
                        }
                }
            }
            if (interestingPointsCtr > pointsCtr * minFill)
                fitCtr == -1;
            if (fitCtr == 0) {
                std::cout << filename << " " << std::flush;
                xOffset = -mat.cols / 2 - 16 + rng.randint(32);
                yOffset = -mat.rows / 2 - 16 + rng.randint(32);
            }
        }
    }
}
void OpenCVPicture::randomCrop(RNG &rng, int subsetSize) {
  assert(subsetSize <= std::min(mat.rows, mat.cols));
  cropImage(mat, rng.randint(mat.cols - subsetSize),
            rng.randint(mat.rows - subsetSize), subsetSize, subsetSize);
  xOffset = yOffset = -subsetSize / 2;
}
void OpenCVPicture::jiggle(RNG &rng, int offlineJiggle) {
  xOffset += rng.randint(offlineJiggle * 2 + 1) - offlineJiggle;
  yOffset += rng.randint(offlineJiggle * 2 + 1) - offlineJiggle;
}