今回は、ある用途に使いたかったので、OpenCVで入力画像を任意の分割数(M×N)で分割するプログラムを書いたため、それを共有します。
今回の環境
・OS : Windows10(64bit)
・Visual Studio 2015 Community
・OpenCV 2.4.11
(上記全て環境構築済の状態でビルド)
今回はOpenCVは環境済の状態でスタートするので、OpenCVの環境構築は以下の記事などを参照してください。
過去記事①:Nugetを使ってOpenCVの環境構築(Visual Studio 2015)
過去記事②:Visual Studio 2015でOpenCV 3.4環境構築(Windows10)
ソースコード
ソースコードは以下となります。
#include <opencv2/opencv.hpp> | |
#include <iostream> | |
int main(int argc, char* argv[]) { | |
int col_num = 11; // 列方向の分割数 | |
int row_num = 7; // 行方向の分割数 | |
cv::Mat input_image = cv::imread("test1.jpg"); // 分割する画像の取得 | |
if (input_image.empty() == true) { | |
std::cerr << "入力画像が見つからない" << std::endl; | |
return false; | |
} | |
int width = input_image.cols; // 入力画像の横の長さ | |
int height = input_image.rows; // 入力画像の縦の長さ | |
std::cout << "Width = " << width << " / Height = " << height << std::endl; | |
int s_width = width % col_num; // 横方向の余り | |
int* div_width = new int[col_num]; // 分割後画像の横の長さを入れる配列 | |
for (int c = 0; c < col_num; c++) { | |
if (s_width > 0) { | |
div_width[c] = width / col_num + 1; // 余りを割り当てる | |
s_width--; | |
} | |
else { | |
div_width[c] = width / col_num; | |
} | |
} | |
int s_height = height % row_num; // 縦方向の余り | |
int* div_height = new int[row_num]; // 分割後画像の縦の長さを入れる配列 | |
for (int r = 0; r < row_num; r++) { | |
if (s_height > 0) { | |
div_height[r] = height / row_num + 1; // 余りを割り当てる | |
s_height--; | |
} | |
else { | |
div_height[r] = height / row_num; | |
} | |
} | |
// 分割画像の出力 | |
int x = 0; | |
int y = 0; | |
for (int r = 0; r < row_num; r++) { | |
for (int c = 0; c < col_num; c++) { | |
// 分割する画像の(x, y, width, height)をRectに入力 | |
cv::Rect crop_region = cv::Rect(x, y, div_width[c], div_height[r]); | |
std::cout << "DIV " << (c + r * col_num) << " RECT : " << crop_region << std::endl; | |
// 分割画像を取得 | |
cv::Mat div_image = input_image(crop_region); | |
// 画像の出力 | |
std::string filename = cv::format("output_%03d.png", c + r * col_num); | |
cv::imwrite(filename, div_image); | |
x += div_width[c]; | |
} | |
y += div_height[r]; | |
x = 0; | |
} | |
return 0; | |
} |
「col_num」に列方向の分割数を「row_num」に行方向の分割数を入れ、入力画像の名前を“test1.jpg“としました。
この部分は好きなように変更してください。
もっと効率の良い書き方もある気がしますが、ひとまず今回は実装することを優先で作ってみました。
実行結果
今回は以下の画像を入力画像としてみました。
(1) col_num=3 / row_num=2(横方向3分割、縦方向2分割)
以下のような出力結果が得られました。横方向に3分割、縦方向に2分割されています。
(2) col_num=11 / row_num=7(横方向11分割、行方向7分割)
かなり多い分割数でも以下のように対応できます。
フォルダに並べると、正常に分割できていそうなことがわかりました。
まとめ
詳細なソースコードの解説までできていませんが、もし画像を等分割したいというときには使ってみてください。
分割数や入力画像名は、本当は引数にして外から与えられるようにした方が使いやすいような気はしますが、今回はそこまでは作りこんでいません。