CrowHop
CrowHop

Reputation: 59

Make 32x32 sections on an image in C++ OpenCV?

I want to take a gray scaled image and divide it into 32x32 sections. Each section will contain pixels and based their intensity and volume, they would be considered a 1 or a 0.

My thought is that I would name the sections like "(x,y)". For example:

Section(1,1) contains this many pixels that are within this range of intensity so this is a 1.

Does that make sense? I tried looking for the answer to this question but dividing up the image into overlaying sections doesn't seem to yield any results in the OpenCV community. Keep in mind I don't want to change the way the image looks, just divide it up into a 32x32 table with (x,y) being a "section" of the picture.

Upvotes: 0

Views: 201

Answers (1)

Nejc
Nejc

Reputation: 937

Yes you can do that. Here is the code. It is rough around the edges, but it does what you request. See comments in the code for explanations.

#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>

struct BradleysImage
{
  int rows;
  int cols;

  cv::Mat data;

  int intensity_threshold;
  int count_threshold;

  cv::Mat buff = cv::Mat(32, 32, CV_8UC1);

  // When we call the operator with arguments y and x, we check
  // the region(y,x). We then count the number of pixels within
  // that region that are greater than some threshold. If the 
  // count is greater than desired number, we return 255, else 0.
  int operator()(int y, int x) const
  {
    int j = y*32;
    int i = x*32;

    auto window = cv::Rect(i, j, 32, 32);

    // threshold window contents
    cv::threshold(data(window), buff, intensity_threshold, 1, CV_THRESH_BINARY);

    int num_over_threshold = cv::countNonZero(buff);

    return num_over_threshold > count_threshold ? 255 : 0;
  }

};

int main() {

  // Input image
  cv::Mat img = cv::imread("walken.jpg", CV_8UC1);

  // I resize it so that I get dimensions divisible 
  // by 32 and get better looking result
  cv::Mat resized;
  cv::resize(img, resized, cv::Size(3200, 3200));

  BradleysImage b; // I had no idea how to name this so I used your nick
  b.rows = resized.rows / 32;
  b.cols = resized.cols / 32;
  b.data = resized;
  b.intensity_threshold = 128; // just some threshold
  b.count_threshold = 512; 

  cv::Mat result(b.rows -1, b.cols-1, CV_8UC1);
  for(int y = 0; y < result.rows; ++y)
    for(int x = 0; x < result.cols; ++x)
      result.at<uint8_t>(y, x) = b(y, x);


  imwrite("walken.png", result); 

  return 0;
}

I used Christopher Walken's image from Wikipedia and obtained this result:

walken

Upvotes: 2

Related Questions