FlyCapture SDKからopenCVで使える形に画像を変換する


# はじめに

## FlyCapture SDK

研究等でよく利用されるPoint Grey製CCDカメラを扱うための専用SDKです。
`openCV`からカメラオープンできないため、処理したい場合は`Mat型`に変換する必用があります。
プラットフォームは、
 
 - Windows
 - Ubuntu(LTSのみ),
 - ARM
 
 に対応しており、言語は、
 

 - C
 - C++
 - C#
 - Visual Basic .NET
 - ActiveX
 - DirectShow
 - Python(トップページに記載はありませんが公式wrapperが存在します)

をサポートしています。

SDKのダウンロードは[こちらから](https://www.ptgrey.com/flycapture-sdk)(登録が必要です。)
PDFで公式リファレンスもありますが残念ながら英語です。


## 使用する言語

今回はC++, Pythonでの変換について扱います。
他言語については筆者がそもそも触れたことがないため説明できませんが、概ねやることは同じだと思います。

また、今回は`opencv3.10`を使用しております。

# C++

VisualStudio2015を使用、環境構築は省略させていただきます。


```c++

	Error error;
	BusManager busMgr;
	unsigned int numCameras;
	PGRGuid guid;
	Camera cam;
	Image rawImage, convertedImage;
	IplImage *cv_image;
	cv::Mat imgSub;
	cv::Rect rect;


    //=====================
    //  カメラの起動
    //=====================

	error = busMgr.GetNumOfCameras(&numCameras);
	if (error != PGRERROR_OK) {
		error.PrintErrorTrace();
		return -1;
	}

	printf("Number of cameras detected: %u\n", numCameras);
	if (numCameras != 1)
		return -1;

	error = busMgr.GetCameraFromIndex(0, &guid);
	if (error != PGRERROR_OK) {
		error.PrintErrorTrace();
		return -1;
	}

	error = cam.Connect(&guid);
	if (error != PGRERROR_OK) {
		error.PrintErrorTrace();
		return -1;
	}

	error = cam.StartCapture();
	if (error != PGRERROR_OK) {
		error.PrintErrorTrace();
		return -1;
	}

	error = cam.RetrieveBuffer(&rawImage);
	if (error != PGRERROR_OK) {
		error.PrintErrorTrace();
		return -1;
	}

	error = cam.RetrieveBuffer(&rawImage);
	if (error != PGRERROR_OK) {
		error.PrintErrorTrace();
		return -1;
	}


    //=====================
    //  Image => cv::Mat
    //=====================


    cv::Mat writer_img(h, w, CV_8UC3, convertedImage.GetData());

    //// 筆者の環境では上下が反転するため以下の一行も追加
    //cv:Flip(writer_img, writer_img);

```

- 2017/9/13
 
コメントにて [yumetodo](http://qiita.com/yumetodo)様からご指摘頂き、コードを変更致しました。動作も確認済みです。

動作確認用に環境を再構築すれば動いたのですが、筆者の環境ではなぜか駄目だったため、
同じような症状の方は変更前のコードを残しておきますのでこちらを参考にしてください。

```c++

    //=====================
    //  Image => cv::Mat
    //=====================

    // カメラ画像をIplImageに変換
    error = rawImage.Convert(PIXEL_FORMAT_BGR, &convertedImage);
    if (error != PGRERROR_OK) {
        error.PrintErrorTrace();
        return -1;
    }

   // コピー先のcv_imageの初期化
    int w = rawImage.GetCols(), h = rawImage.GetRows();
    cv_image = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 3);

    // cv_imageのメモリにコピー    
    memcpy(cv_image->imageData, convertedImage.GetData(), w * h * 3);

    // 筆者の環境では上下が反転するため以下の一行も追加
    //cvFlip(cv_image, cv_image); 

    // IplImageからMatへ変換
    cv::Mat writer_img = cv::cvarrToMat(cv_image);
```


# Python

使用するpythonのバージョンは`3.5.2`です。
2系での動作確認はしておりませんが、Wrapperライブラリはどちらもサポートしているので、参考程度にはなるかと思います。

```py3

import PyCapture2
import cv2

#============================
# カメラの起動
#============================

bus = PyCapture2.BusManager()
cam = PyCapture2.Camera()
uid = bus.getCameraFromIndex(0)
cam.connect(uid)

numCams = bus.getNumOfCameras()
print("Number of cameras detected: ", numCams)
if not numCams:
	print("Insufficient number of cameras. Exiting...")
	exit()

cam.startCapture()


#============================
# opencvで利用できる形に変換
#============================

# 画像の取得
tmp_image = cam.retrieveBuffer()

# numpy配列化(pythonのopencvはnumpy配列を使用)
row_bytes = float(len(tmp_image.getData()))/float(tmp_image.getRows())
cv_image = np.array(tmp_image.getData(), dtype="uint8").reshape((tmp_image.getRows(), tmp_image.getCols()));

# 色空間を指定(これをしないとグレー画像になる)
raw_image = cv2.cvtColor(cv_image, cv2.COLOR_BAYER_BG2BGR)

```