ラベル 画像処理 の投稿を表示しています。 すべての投稿を表示
ラベル 画像処理 の投稿を表示しています。 すべての投稿を表示

2016年1月3日日曜日

OpenCVを使ったCSVファイルの入出力。

メモ。

OpenCVのMatの値をCSVで保存する。


  char name[256]; //ファイル名

   sprintf_s(name, 256, "ディレクトリ名\\ファイル名%d.csv", counter);
   //処理全体をループ内に入れてcounterを回せば、ファイル名に連番が付く

   //フォルダがない場合は作成(direct.hをインクルードしておく )
   if (_mkdir("ディレクトリ名") == 0);

   //#include <direct.h>を忘れない
   ofstream save(name);

   double output;
   for (int y = 0; y < height; ++y){ //row:列
    for (int x = 0; x < width; ++x){
     output = data.at<double>(y, x); //画像というか単純に行列のデータ
     save << dec << output << ",";

    }
    //改行
    save << endl;
   }

   //解放
   save.close();



cv::Mat data はCV_64FC1とかを想定したもの。


で、for文で1ピクセルずつ回しているけど、書くのが面倒だったら↓みたいにOpenCVの関数使えば1行で書ける。



 //csv変換して出力
 save << cv::format(data, "csv");



以上。


2016年1月1日金曜日

OpenCVのcv::Matについてメモ(画素の扱いとか)

OpenCVのcv::Matについてメモ

勉強し始めた時、あれMatのチャンネルって何?
あれ?どうやって各画素値いじるの?
あれ全部真っ白なっちゃった!?orzってなったのでそのメモ


#include <iostream>
#include <opencv2\opencv.hpp>


#define height 100
#define width 100

 void main(){

  double* data = new double[height*width](); //0で初期化
  //省略したけど、dataになにかいろんな数値入れておく
  /*
  .... dataに数値入れる処理
  for :
  data[i] = a とかで数値入れる
  */

  //dataをMatにぶち込む
  //32F、64Fにすれば255以上の数値も扱える
  Mat input(height, width, CV_64FC1, data);


  Mat img(input.rows, input.cols, CV_8UC3); //inputと同じ行数と列数を用意


  //ここでMatの各要素にアクセスする
  for (int y = 0; y < input.rows; ++y) {
   for (int x = 0; x < input.cols; ++x) {

    //ピクセルにアクセスするためのインデックス
    //G,B,Rの順 チャンネル数は3つ必要→Matは1次元だから3倍する
    int index = ((y * input.cols) + x) * 3;

    //とりあえず画素に何か数値入れる
    //doubleの数値を扱えるのは .atだけらしい
    int rgb = input.at<double>(y, x) + (x * y) % 255; //255諧調に

    //.dataでは扱える数値の最大が255
    //B,G,Rと連続しているのでindex, index+1, index+2でアクセス可能
    img.data[index] = rgb;
    img.data[index + 1] = rgb;
    img.data[index + 2] = rgb;
    //これで1ピクセルの色を扱える

   }
  }


  delete[] data; //明示的に解放

 }

こんな感じでやる。

#define height 100
#define width 100
は定数。const int とかでもいいと思うけどとりあえず、ここではあまり重要じゃない。

double* data = new double[height*width]();
cv::Mat input(height, width, CV_64FC1, data);
height*widthの1次元配列を確保。()をつけると0で初期化できるらしい。
heigh*widthつまり100x100の行列。
CV_64FC1はdouble型の1チャンネルの行列。
CV_8UC1とか
CV_8UC3とかいろいろある。C1とかC2がチャンネル数。
RGBの画像を扱いたかったら、CV_8UC3ってやる。R、G、Bそれぞれ1チャンネルずつ使うから。
でも、想像するのは1次元配列なのでデータのアクセスではじめはややこしいと思った。

3x3の画像    数値をいじるときの想像
■■□  →  ■■□■□■□■■
■□■     [0][1] .....                [8]  
□■■   

3x3のRGB画像だったら
BGR BGR BGR   →   BGR BGR BGR BGR BGR BGR BGR BGR BGR
BGR BGR BGR        [0][1][2]     .......                       [24][25][26]
BGR BGR BGR 


input.at<double>(y, x)
255以上の数値を扱うときは.atを使う。
あとCV_32FとかCV_64FとかでMatを作る

img.data[index]         //B
img.data[index + 1]    //G
img.data[index + 2]    //R
B,G,Rと1ピクセルを1次元配列の要素3つで扱うので
3チャンネルでMatを作っておく。
.dataでアクセスして、+1, +2で3つ分。



以上。



2014年8月29日金曜日

画像の書出(1)【OpneCV】【C++】


やったことのメモ。

cv::imread("filename", img);   // img : 画像    filename : この名前で保存
※参考: http://opencv.jp/opencv-2.1/cpp/reading_and_writing_images_and_video.html



画像の書出
#include <opencv2\opencv.hpp>

int main(int argc, char* argv[]){

 cv::Mat img = cv::imread("lena.jpg");

 //グレースケール
 cv::Mat imgG = cv::imread("lena.jpg", 0);

 //保存
 cv::imwrite("lena2.jpg", img);
 cv::imwrite("lenaG2.jpg", imgG);
}


実行結果
元画像 lena.jpg:


保存 lena2,jpg, lenaG2.jpg:




使用した画像はOpenCVのsampleに入っていたもの。
JPEGの品質(CV_IMWRITE_JPEG_QUALITY)はデフォルトで95(0-100)。値が高いほど高品質。







画像の読込【OpenCV】【C++】

やったことのメモ。

cv::Mat img = cv::imread("filename");    // 画像の読み込み
cv::namedWindow("window name");      // ウィンドウ作成
cv::imshow("window name", img);         // ウィンドウ表示
cv::waitKey(0);                        // 0のとき何かキー入力があるまで待つ

※参考: http://opencv.jp/opencv-2.1/cpp/user_interface.html



画像の読込と表示
#include <iostream>
#include <opencv2\opencv.hpp>

int main(int argc, char* argv[]){

 cv::Mat img = cv::imread("lena.jpg");

 //グレースケール
 cv::Mat imgG = cv::imread("lena.jpg", 0); //flag=0でグレースケール

 cv::namedWindow("img");
 cv::namedWindow("imgGray");
 cv::imshow("img", img);
 cv::imshow("imgGray", imgG);
 cv::waitKey(0);
}


実行結果



使用した画像はOpenCVのsampleに入っていたもの。