WindowsのVisual C++を利用したOpenCVプログラミング入門

Tweet


OpenCVプログラミング入門です.WindowsのVisual Studioを使ったC/C++プログラミングです.OpenCVプログラミングの基本を短時間で修得します.


IrfanViewのインストール


Visual Studioのインストール

インストール時,「C++によるデスクトップ開発」にチェックを入れること.


OpenCVのインストール

ダウンローダを実行すると解凍されるだけ.解凍されたフォルダをC:\の直下など,インストールしたいディレクトリに置く.

[コントロールパネル]を開く.[システムとセキュリティ]-[システム]-[システムの詳細設定]-[環境変数].[システム環境変数]-[PATH]を[編集].[新規]を押して,OpenCVをインストールしたディレクトリの\build\x64\vc15\binを記入する.


Visual Studioの設定

[Visual Studio]を起動.[新しいプロジェクトの作成]を選ぶ.C++の[コンソールアプリ]を選ぶ.保存先フォルダを指定.プロジェクト名を入力.

[ソリューションプラットフォーム]を[x64]にする.

[プロジェクト]-[プロパティ]を開く.[構成プロパティ]-[C/C++]-[プリコンパイル済みヘッダー]-[プリコンパイル済みヘッダー]で[プリコンパイル済みヘッダーを使用しない]を選ぶ.

[ビルド]-[ソリューションのビルド]でビルドされる.[1 正常終了]と表示されればビルド成功.

[デバッグ]-[デバッグの開始]で実行.

[このウィンドウを閉じるには,任意のキーを押してください...]と表示されたら,任意のキーを押す.

#include <iostream>
using namespace std;

int main()
{

    cout << "Visual C++ sample" << endl;
}


行列計算のプログラミング

[プロジェクト]-[プロパティ]を開く.

[構成プロパティ]-[C/C++]-[全般]-[追加のインクルードディレクトリ]に,OpenCVをインストールしたディレクトリの\build\includeを記入.

[構成プロパティ]-[リンカー]-[全般]-[追加のライブラリディレクトリ]に,OpenCVをインストールしたディレクトリの\build\x64\vc15\libを記入.

#if _DEBUG
#pragma comment(lib, "opencv_world430d.lib")
#else
#pragma comment(lib, "opencv_world430.lib")
#endif

#include <iostream>
using namespace std;

#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    Mat mata = Mat::zeros(2, 2, CV_64F);
    Mat vecx = Mat::zeros(2, 1, CV_64F);
    Mat vecb;

    mata.at<double>(0, 0) = 1.0;
    mata.at<double>(0, 1) = 2.0;
    mata.at<double>(1, 0) = 3.0;
    mata.at<double>(1, 1) = 4.0;
    vecx.at<double>(0, 0) = 2.0;
    vecx.at<double>(1, 0) = 1.0;
    vecb = mata * vecx;

    cout << "a=" << endl << mata << endl << endl;
    cout << "x=" << endl << vecx << endl << endl;
    cout << "b=" << endl << vecb << endl << endl;

    return 0;
}


お絵かきプログラミング

#if _DEBUG
#pragma comment(lib, "opencv_world430d.lib")
#else
#pragma comment(lib, "opencv_world430.lib")
#endif

#include <iostream>
using namespace std;

#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    Mat img = Mat::zeros(480, 640, CV_8UC3);

    line(img, Point(100, 100), Point(200, 100), Scalar(0, 0, 255));
    rectangle(img, Point(100, 200), Point(200, 300), Scalar(0, 255, 0));
    circle(img, Point(400, 200), 50, Scalar(255, 0, 0));

    imshow("opencv program", img);
    waitKey();

    return 0;
}


画像処理プログラミングの基本的な骨組み

meal41.jpg

#if _DEBUG
#pragma comment(lib, "opencv_world430d.lib")
#else
#pragma comment(lib, "opencv_world430.lib")
#endif

#include <iostream>
using namespace std;

#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    Mat input = imread("meal41.jpg", IMREAD_COLOR);
    if (!input.data) {
        cout << "cannot open input file" << endl; return 1;
    }

    Mat output = Mat(input.rows, input.cols, CV_8UC3);
    for (int y = 0; y < input.rows; y++) {
        for (int x = 0; x < input.cols; x++) {
            unsigned char r = input.at<Vec3b>(y, x)[2];
            unsigned char g = input.at<Vec3b>(y, x)[1];
            unsigned char b = input.at<Vec3b>(y, x)[0];
            output.at<Vec3b>(y, x)[2] = (unsigned char)(0.9 * (double)r);
            output.at<Vec3b>(y, x)[1] = (unsigned char)(0.7 * (double)g);
            output.at<Vec3b>(y, x)[0] = (unsigned char)(0.4 * (double)b);
        }
    }
    imwrite("output.bmp", output);

    return 0;
}


Pythonでの実装例

# -*- coding: utf-8 -*-

import cv2

def main():
    input = cv2.imread("meal41.jpg")
    if input is None:
        print('cannot open input file')
        return
    row, col, channel = input.shape

    output = input.copy()
    for y in range(0, row):
        for x in range(0, col):
            r = input[y, x, 2]
            g = input[y, x, 1]
            b = input[y, x, 0]
            output[y, x, 2] = 0.9 * r
            output[y, x, 1] = 0.7 * g
            output[y, x, 0] = 0.4 * b

    cv2.imwrite("output.bmp", output)

if __name__ == '__main__':
    main()


MATLABでの実装例

input = imread('meal41.jpg');
[row,col,channel]=size(input);
output=input;
for y=1:row
    for x=1:col
        r=input(y,x,1);
        g=input(y,x,2);
        b=input(y,x,3);
        output(y,x,1)=0.9*r;
        output(y,x,2)=0.7*g;
        output(y,x,3)=0.4*b;
    end
end
imwrite(output, 'output.bmp');


近傍画素を使った画像処理プログラミング

grayscale.jpg

#if _DEBUG
#pragma comment(lib, "opencv_world430d.lib")
#else
#pragma comment(lib, "opencv_world430.lib")
#endif

#include <iostream>
using namespace std;

#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    Mat input = imread("grayscale.jpg", IMREAD_GRAYSCALE);
    if (!input.data) {
        cout << "cannot open input file" << endl; return 1;
    }

    Mat output = Mat(input.rows, input.cols, CV_8U);
    for (int y = 0; y < input.rows; y++) {
        for (int x = 0; x < input.cols; x++) {
            int num = 0;
            double val = 0.0;
            for (int yy = y - 1; yy <= y + 1; yy++) {
                for (int xx = x - 1; xx <= x + 1; xx++) {
                    if (xx >= 0 && yy >= 0 && xx < input.cols && yy < input.rows) {
                        val += (double)input.at<uchar>(yy, xx);
                        num++;
                    }
                }
            }
            output.at<uchar>(y, x) = (unsigned char)(val / (double)num);
        }
    }
    imwrite("output.bmp", output);

    return 0;
}


照度差ステレオ法の実装例

input0.bmp
input1.bmp
input2.bmp

inside.byte
Normal2Height.exe

#if _DEBUG
#pragma comment(lib, "opencv_world430d.lib")
#else
#pragma comment(lib, "opencv_world430.lib")
#endif

#include <iostream>
#include <fstream>
using namespace std;

#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    Mat input[3];
    input[0] = imread("input0.bmp", IMREAD_GRAYSCALE);
    input[1] = imread("input1.bmp", IMREAD_GRAYSCALE);
    input[2] = imread("input2.bmp", IMREAD_GRAYSCALE);
    if (!input[0].data || !input[1].data || !input[2].data) {
        cout << "cannot open input file" << endl; return 1;
    }
    int rows = input[0].rows;
    int cols = input[0].cols;

    Mat matl = Mat::zeros(3, 3, CV_64F);
    matl.at<double>(0, 0) = 1.58546E-17;
    matl.at<double>(0, 1) = 0.258819045;
    matl.at<double>(0, 2) = 0.965925826;
    matl.at<double>(1, 0) = -0.353553391;
    matl.at<double>(1, 1) = -0.353553391;
    matl.at<double>(1, 2) = 0.866025404;
    matl.at<double>(2, 0) = 0.353553391;
    matl.at<double>(2, 1) = -0.353553391;
    matl.at<double>(2, 2) = 0.866025404;
    Mat invl = matl.inv();

    Mat output = Mat(rows, cols, CV_32FC3);
    for (int y = 0; y < rows; y++) {
        for (int x = 0; x < cols; x++) {
            Mat veci = Mat::zeros(3, 1, CV_64F);
            veci.at<double>(0, 0) = (double)input[0].at<uchar>(y, x);
            veci.at<double>(1, 0) = (double)input[1].at<uchar>(y, x);
            veci.at<double>(2, 0) = (double)input[2].at<uchar>(y, x);
            Mat vecn = invl * veci;
            double r = norm(vecn);
            if (r > 1.0e-15) {
                vecn.at<double>(0, 0) /= r;
                vecn.at<double>(1, 0) /= r;
                vecn.at<double>(2, 0) /= r;
            }
            output.at<Vec3f>(y, x)[0] = (float)vecn.at<double>(0, 0);
            output.at<Vec3f>(y, x)[1] = (float)vecn.at<double>(1, 0);
            output.at<Vec3f>(y, x)[2] = (float)vecn.at<double>(2, 0);
        }
    }

    ofstream fout;
    fout.open("normal.float", ios::out | ios::trunc | ios::binary);
    for (int y = 0; y < rows; y++) {
        for (int x = 0; x < cols; x++) {
            for (int i = 0; i < 3; i++) {
                fout.write((char*)&output.at<Vec3f>(y, x)[i], sizeof(float));
            }
        }
    }
    fout.close();

    return 0;
}


カメラキャリブレーションの実装例

image1.jpg
image2.jpg

#if _DEBUG
#pragma comment(lib, "opencv_world430d.lib")
#else
#pragma comment(lib, "opencv_world430.lib")
#endif

#include <iostream>
using namespace std;

#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
    Mat input[2];
    input[0] = imread("image1.jpg", IMREAD_COLOR);
    input[1] = imread("image2.jpg", IMREAD_COLOR);
    if (!input[0].data || !input[1].data) {
        cout << "cannot open input file" << endl; return 1;
    }

    Mat output[2];
    output[0] = input[0].clone();
    output[1] = input[1].clone();

    vector<vector<Vec3f>> list3d;
    vector<vector<Vec2f>> list2d;

    vector<Vec3f> item3d[2];
    vector<Vec2f> item2d[2];

    item3d[0].push_back(Vec3f(1.0f, 0.0f, 0.0f));
    item2d[0].push_back(Vec2f(234.0f, 306.0f));
    item3d[0].push_back(Vec3f(0.0f, 1.0f, 0.0f));
    item2d[0].push_back(Vec2f(448.0f, 265.0f));
    item3d[0].push_back(Vec3f(0.0f, 0.0f, 1.0f));
    item2d[0].push_back(Vec2f(320.0f, 90.0f));
    item3d[0].push_back(Vec3f(1.0f, 1.0f, 0.0f));
    item2d[0].push_back(Vec2f(391.0f, 370.0f));
    item3d[0].push_back(Vec3f(0.0f, 1.0f, 1.0f));
    item2d[0].push_back(Vec2f(475.0f, 121.0f));
    item3d[0].push_back(Vec3f(1.0f, 0.0f, 1.0f));
    item2d[0].push_back(Vec2f(225.0f, 147.0f));
    item3d[0].push_back(Vec3f(1.0f, 1.0f, 1.0f));
    item2d[0].push_back(Vec2f(413.0f, 196.0f));

    item3d[1].push_back(Vec3f(1.0f, 0.0f, 0.0f));
    item2d[1].push_back(Vec2f(174.0f, 249.0f));
    item3d[1].push_back(Vec3f(0.0f, 1.0f, 0.0f));
    item2d[1].push_back(Vec2f(384.0f, 276.0f));
    item3d[1].push_back(Vec3f(0.0f, 0.0f, 1.0f));
    item2d[1].push_back(Vec2f(298.0f, 69.0f));
    item3d[1].push_back(Vec3f(1.0f, 1.0f, 0.0f));
    item2d[1].push_back(Vec2f(244.0f, 359.0f));
    item3d[1].push_back(Vec3f(0.0f, 1.0f, 1.0f));
    item2d[1].push_back(Vec2f(404.0f, 154.0f));
    item3d[1].push_back(Vec3f(1.0f, 0.0f, 1.0f));
    item2d[1].push_back(Vec2f(138.0f, 125.0f));
    item3d[1].push_back(Vec3f(1.0f, 1.0f, 1.0f));
    item2d[1].push_back(Vec2f(226.0f, 239.0f));

    list3d.push_back(item3d[0]);
    list3d.push_back(item3d[1]);
    list2d.push_back(item2d[0]);
    list2d.push_back(item2d[1]);

    Size imgsize = Size(input[0].cols, input[0].rows);
    Mat intrinsic = (Mat_<double>(3, 3) <<
        1000.0, 0.0, (double)input[0].cols / 2.0,
        0.0, 1000.0, (double)input[0].rows / 2.0,
        0.0, 0.0, 1.0);
    Mat dist = Mat::zeros(1, 4, CV_64F);
    vector<Mat> vecr;
    vector<Mat> vect;

    calibrateCamera(list3d, list2d, imgsize, intrinsic, dist, vecr, vect,
        CALIB_USE_INTRINSIC_GUESS | CALIB_FIX_PRINCIPAL_POINT | CALIB_FIX_ASPECT_RATIO | CALIB_ZERO_TANGENT_DIST |
        CALIB_FIX_K1 | CALIB_FIX_K2 | CALIB_FIX_K3 | CALIB_FIX_K4 | CALIB_FIX_K5 | CALIB_FIX_K6);

    cout << "カメラ内部行列" << endl;
    cout << intrinsic << endl;
    cout << endl;

    cout << "平行移動ベクトル" << endl;
    cout << vect.at(0) << endl;
    cout << vect.at(1) << endl;
    cout << endl;

    Mat matr[2];
    Rodrigues(vecr.at(0), matr[0]);
    Rodrigues(vecr.at(1), matr[1]);
    cout << "回転行列" << endl;
    cout << matr[0] << endl;
    cout << matr[1] << endl;
    cout << endl;

    for (int c = 0; c < 2; c++) {
        for (int y = -1; y <= 2; y++) {
            Mat point3d1 = Mat::zeros(3, 1, CV_64F);
            point3d1.at<double>(0, 0) = -1.0;
            point3d1.at<double>(1, 0) = (double)y;
            point3d1.at<double>(2, 0) = 0.0;
            point3d1 = intrinsic * (matr[c] * point3d1 + vect.at(c));
            Point point2d1 = Point(
                (int)(point3d1.at<double>(0, 0) / point3d1.at<double>(2, 0)),
                (int)(point3d1.at<double>(1, 0) / point3d1.at<double>(2, 0)));
            Mat point3d2 = Mat::zeros(3, 1, CV_64F);
            point3d2.at<double>(0, 0) = 2.0;
            point3d2.at<double>(1, 0) = (double)y;
            point3d2.at<double>(2, 0) = 0.0;
            point3d2 = intrinsic * (matr[c] * point3d2 + vect.at(c));
            Point point2d2 = Point(
                (int)(point3d2.at<double>(0, 0) / point3d2.at<double>(2, 0)),
                (int)(point3d2.at<double>(1, 0) / point3d2.at<double>(2, 0)));
            line(output[c], point2d1, point2d2, Scalar(0, 0, 255), 3, LINE_AA);
        }
        for (int x = -1; x <= 2; x++) {
            Mat point3d1 = Mat::zeros(3, 1, CV_64F);
            point3d1.at<double>(0, 0) = (double)x;
            point3d1.at<double>(1, 0) = -1.0;
            point3d1.at<double>(2, 0) = 0.0;
            point3d1 = intrinsic * (matr[c] * point3d1 + vect.at(c));
            Point point2d1 = Point(
                (int)(point3d1.at<double>(0, 0) / point3d1.at<double>(2, 0)),
                (int)(point3d1.at<double>(1, 0) / point3d1.at<double>(2, 0)));
            Mat point3d2 = Mat::zeros(3, 1, CV_64F);
            point3d2.at<double>(0, 0) = (double)x;
            point3d2.at<double>(1, 0) = 2.0;
            point3d2.at<double>(2, 0) = 0.0;
            point3d2 = intrinsic * (matr[c] * point3d2 + vect.at(c));
            Point point2d2 = Point(
                (int)(point3d2.at<double>(0, 0) / point3d2.at<double>(2, 0)),
                (int)(point3d2.at<double>(1, 0) / point3d2.at<double>(2, 0)));
            line(output[c], point2d1, point2d2, Scalar(0, 0, 255), 3, LINE_AA);
        }
    }

    imwrite("output1.jpg", output[0]);
    imwrite("output2.jpg", output[1]);

    return 0;
}


4コマ漫画のコマ枠の検出

http://non117.hatenablog.com/entry/2014/12/20/175053


もどる