【问题标题】:How to split an image into M x N tiles如何将图像拆分为 M x N 个图块
【发布时间】:2022-02-02 17:26:01
【问题描述】:

如何使用 OpenCV 和 C++ 将 Mat 对象/图像拆分为 M x N 相等的块,并将这些块从左到右和自上而下存储到 Mat 向量中?

非常感谢

【问题讨论】:

  • 不确定您所说的“拆分”是什么意思,但您可以使用cv::Rect 保存cv::Mat 的“部分”,并且可以将它们保存在矢量或任何您喜欢的位置。见example

标签: c++ opencv


【解决方案1】:

here 给出的相反问题的解决方案一致,应该这样做:

#include <opencv2/opencv.hpp>

std::vector<cv::Mat> splitImage( cv::Mat & image, int M, int N )
{
  // All images should be the same size ...
  int width  = image.cols / M;
  int height = image.rows / N;
  // ... except for the Mth column and the Nth row
  int width_last_column = width  + ( image.cols % width  );
  int height_last_row   = height + ( image.rows % height );

  std::vector<cv::Mat> result;

  for( int i = 0; i < N; ++i )
  {
    for( int j = 0; j < M; ++j )
    {
      // Compute the region to crop from
      cv::Rect roi( width  * j,
                    height * i,
                    ( j == ( M - 1 ) ) ? width_last_column : width,
                    ( i == ( N - 1 ) ) ? height_last_row   : height );

      result.push_back( image( roi ) );
    }
  }

  return result;
}


int main()
{
  cv::Mat image = cv::imread( "image.png" );
  std::vector<cv::Mat> array_of_images = splitImage( image, 3, 2 );

  for( int i = 0; i < array_of_images.size(); ++i )
  {
    cv::imshow( "Image " + std::to_string( i ), array_of_images[i] );
  }
  cv::waitKey( 0 );
}

【讨论】:

    【解决方案2】:

    这里是一个例子:

    您在一个循环中一个接一个地获取矩形,并使用crop 从整个图片中捕获选定的部分。

    请注意,全图可能无法完美分割,因此每行/列中的一个部分可能会比​​其他部分稍大。

    #include <opencv2/opencv.hpp>
    #include <highgui.h>
    #include <iostream>
    #include <string>
    #include <vector>
    
    //usage: app pic.ext M N
    int main(int argc, char* argv[])
    {
        int M=0,N=0;
        
        M = std::stoi(argv[2]);
        N = std::stoi(argv[3]);
        
        cv::Mat img = cv::imread(argv[1]);
        if (img.empty())
        {
            std::cout << "failed to open the image" << std::endl;
            return -1;        
        }
        std::vector<std::vector<cv::Mat>> result;
        /* Regular size */
        int crop_width = img.size().width / M;
        int crop_height = img.size().height / N;
        /* column / row first part size when part size is not evenly divided*/
        int crop_width1 = img.size().width - (M-1)*crop_width;
        int crop_height1 = img.size().height - (N-1)*crop_height;
        
        int offset_x = 0;
        int offset_y = 0;
        for(int i = 0; i < M; i++) //rows
        {
            std::vector<cv::Mat> tmp;
            offset_x = 0;
            for(int j=0; j< N; j++) //columns
            {
                cv::Rect roi;
                roi.x = offset_x;
                roi.y = offset_y 
                roi.width = (j>0) ? crop_width :  crop_width1;
                roi.height = (i>0) ? crop_height : crop_height1;
                offset_x += roi.width;
                /* Crop the original image to the defined ROI */
                cv::Mat crop = img(roi);
                /* You can save part to a file: */
                //cv::imwrite(std::to_string(i) + "x" + std::to_string(j)+".png", crop);
                tmp.push_back(crop);
                
                
            }
            result.push_back(tmp);
            offset_y += (i>0) crop_height : crop_height1; 
        }
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-30
      相关资源
      最近更新 更多