Qtで作るBeagleBoneのプログラムで画像処理ライブラリOpenCVを使う手順についてメモしておきます。
QtCreatorが動作するUbuntu 15.04 i386上でarm用のopencvを構築します。
こちらのサイトを参考にしました
1. Opencvのソースをダウンロードして解凍します
~$ mkdir opencv ~$cd opencv ~/opencv$ wget -O opencv-3.1.0.zip https://github.com/opencv/opencv/archive/3.1.0.zip ~/opencv$ wget -O opencv_contrib-3.1.0.zip https://github.com/opencv/opencv_contrib/archive/3.1.0.zip ~/opencv$ unzip opencv-3.1.0.zip ~/opencv$ unzip opencv_contrib-3.1.0.zip
2.使用するコンパイラに合わせてopencv-3.1.0/platforms/linux/arm-qnueabi.toolchain.cmakeを修正します
GCC_COMPILER_VERSIONを”4.6″から”5″に変更しました
set(GCC_COMPILER_VERSION "5" CACHE STRING "GCC Compiler version")
3. cmakeとmakeで構築してインストールします
~/opencv$ cd opencv-3.1.0 ~/opencv/opencv-3.1.0$ mkdir build-arm ~/opencv/opencv-3.1.0$ cd build-arm ~/opencv/build/build-arm$ cmake -D CMAKE_BUILD_TYPE=RELEASE \ -D CMAKE_INSTALL_PREFIX=/opt/opencv3.1-arm \ -D CMAKE_TOOLCHAIN_FILE=~/opencv/opencv-3.1.0/platforms/linux/arm-gnueabi.toolchain.cmake \ -D CMAKE_AR=/usr/arm-linux-gnueabihf/bin/ar \ -D OPENCV_EXTRA_MODULES_PATH=~/opencv/opencv_contrib-3.1.0/modules \ -D ENABLE_NEON:BOOL=ON \ -D WITH_TBB=ON \ -D BUILD_TBB=ON \ -D WITH_QT=OFF \ -D WITH_OPENGL=OFF \ -D SOFTFP=ON \ .. ~/opencv/opencv-3.1.0/build-arm$ sudo make j2 ~/opencv/opencv-3.1.0/build-arm$ sudo make install
3.BeagleBoneBlackへライブラリを転送します
~$ scp /opt/opencv3.1-arm/lib/* root@192.168.0.xxx:/usr/lib
4.Qtプロジェクトの設定
myproject.pro の最後にインクルードパスとライブラリの参照を追加します
DEPENDPATH += /opt/opencv3.1-arm/include INCLUDEPATH += /opt/opencv3.1-arm/include LIBS += -L/opt/opencv3.1-arm/lib/ \ -lopencv_core \ -lopencv_imgproc \ -lopencv_highgui \ -lopencv_imgcodecs
5. OpenCVのサンプル
Qtデータ形式との変換、2値化
cvfunc.h
#ifndef CVFUNC_H #define CVFUNC_H #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/core/core.hpp" #include <iostream> #include <stdlib.h> extern void read_qimageformat(cv::Mat &mat, const char *filename); extern void read_qimageformat0(cv::Mat &mat, const char *filename); extern void binarize(cv::Mat &mat, const char *filename); extern void detect_plate(cv::Mat &mat, int th); extern void mask_plate(cv::Mat mat, cv::Mat &dst, int th); extern void copypart(cv::Mat src, cv::Mat &dst, int x0, int y0); #endif // CVFUNC_H
cvfunc.cpp
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/core/core.hpp" #include <iostream> #include <stdlib.h> #include "mainwindow.h" #include <QtGui> #include "cvfunc.h" using namespace cv; // copy part of image // input : src,dst: CV_8UC3 void copypart(cv::Mat src, cv::Mat &dst, int x0, int y0) { for(int y=0; y < dst.rows; y++){ for( int x=0; x < dst.cols; x++){ dst.data[y * dst.step + x * dst.elemSize() + 0] // G = src.data[(y+y0) * src.step + (x+x0) * src.elemSize() + 0]; dst.data[y * dst.step + x * dst.elemSize() + 1] // B = src.data[(y+y0) * src.step + (x+x0) * src.elemSize() + 1]; dst.data[y * dst.step + x * dst.elemSize() + 2] // R = src.data[(y+y0) * src.step + (x+x0) * src.elemSize() + 2]; } } } // Detect plate // input : mat: CV_8UC1, th:threshold void detect_plate(cv::Mat &mat, int th) { // srcと同じサイズで8ビット×3チャンネルのMatデータを作成 // cv::Mat (GBR) を QImage (RGB)に入れ替える for(int y=0; y < mat.rows; y++){ for( int x=mat.cols-3; 0 < x ; x--){ if( mat.data[y * mat.step + x] <= th ) mat.data[y * mat.step + x] = 255; else break; } } } // Mask plate // input : mat,dst: CV_8UC1, th:threshold void mask_plate(cv::Mat mat, cv::Mat &dst, int th) { // srcと同じサイズで8ビット×3チャンネルのMatデータを作成 // cv::Mat (GBR) を QImage (RGB)に入れ替える for(int y=0; y < mat.rows; y++){ for( int x=mat.cols-3; 0 < x ; x--){ if( mat.data[y * mat.step + x] <= th ) dst.data[y * dst.step + x] = 255; else break; } } } // // OpenCv形式からQImage形式への変換 // void read_qimageformat(cv::Mat &mat, const char *filename) { // Matにイメージを読み込む Mat src = imread(filename,IMREAD_COLOR); // cv::Mat と QImage で異なるのでRGBの順番を入れ替える cvtColor(src, mat, CV_RGB2BGR); //OpenCVの命令でRGBの順番を入れ替える // 次のようにしてQIMageに変換する //QImage qimg(mat.data, mat.cols, mat.rows, QImage::Format_RGB888); } // // OpenCv形式からQImage形式への変換 // Matの初期化と画素直接アクセスのサンプル // void read_qimageformat0(cv::Mat &mat, const char *filename) { // Matにイメージを読み込む Mat src = imread(filename,IMREAD_COLOR); // srcと同じサイズで8ビット×3チャンネルのMatデータを作成 Mat dst(src.size().height,src.size().width,CV_8UC3); // cv::Mat (GBR) を QImage (RGB)に入れ替える for(int y=0; y < src.rows; y++){ for( int x=0; x < src.cols; x++){ dst.data[y * src.step + x * src.elemSize() + 0] // R = src.data[y * src.step + x * src.elemSize() + 2]; dst.data[y * src.step + x * src.elemSize() + 1] // G = src.data[y * src.step + x * src.elemSize() + 0]; dst.data[y * src.step + x * src.elemSize() + 2] // B = src.data[y * src.step + x * src.elemSize() + 1]; } } mat = dst; } #if 0 // // 二値化 // void binarize(cv::Mat &mat, const char *filename) { // Matにイメージを読み込む Mat src_img = imread(filename,IMREAD_COLOR); // srcと同じサイズで8ビット×1チャンネルのMatデータを作成 Mat gray_img(src_img.size(),CV_8UC1); // グレースケールに変換 //cvtColor(src_img, gray_img, CV_BGR2GRAY); cvtColor(src_img, gray_img, CV_); // 変換先のイメージ作成 Mat bin_img(src_img.size(),CV_8UC1); #if 0 // 二値化、大津の手法(自動的にスレッショルドを決定) threshold(gray_img, bin_img, 0, 255, CV_THRESH_BINARY|CV_THRESH_OTSU); #else // (3)apply an adaptive threshold to a grayscale image adaptiveThreshold(gray_img, bin_img, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, 8); #endif // bin 8bit x 1ch を mat 8bit x 3ch に変換 cvtColor(bin_img, mat, CV_GRAY2RGB); } #else // // 二値化 // void binarize(cv::Mat &mat, const char *filename) { // Matにイメージを読み込む Mat src_img = imread(filename,IMREAD_COLOR); // srcと同じサイズで8ビット×1チャンネルのMatデータを作成 Mat gray_img(src_img.size(),CV_8UC1); // 青色を取り出すグレースケールに変換 //cvtColor(src_img, gray_img, CV_BGR2GRAY); for(int y=0; y < src_img.rows; y++){ for( int x=0; x < src_img.cols; x++){ gray_img.data[y * gray_img.step + x * gray_img.elemSize() + 0] // = src_img.data[y * src_img.step + x * src_img.elemSize() + 0]; // B } } #if 0 // 青色のグレースケール表示 // gray_img 8bit x 1ch を mat 8bit x 3ch に変換 cvtColor(gray_img, mat, CV_GRAY2RGB); #else // 変換先のイメージ作成 Mat bin_img(src_img.size(),CV_8UC1); #if 0 // 二値化、大津の手法(自動的にスレッショルドを決定) threshold(gray_img, bin_img, 0, 255, CV_THRESH_BINARY|CV_THRESH_OTSU); #else // (3)apply an adaptive threshold to a grayscale image adaptiveThreshold(gray_img, bin_img, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 7, 8); #endif // bin 8bit x 1ch を mat 8bit x 3ch に変換 cvtColor(bin_img, mat, CV_GRAY2RGB); #endif } #endif