ROS Resources: Documentation | Support | Discussion Forum | Service Status | Q&A answers.ros.org

ROSでのOpencvの利用について


#1

学生です。
初歩的な質問かと思われますがよろしくお願いします。

今回質問させていただきたいのは
opencvの関数をどのようにしたら利用できるかです。

ウェブカメの画像をopencvにて縦エッジ検出→rvizへの出力をしたいと考え、
練習として カメラからの入力画像のエッジ検出、マーカーをrvizに表示するプログラム(最後に載せます)を書きましたが
コンパイルがうまくいきません。

以下のようなエラーメッセージが出ており
opencvの関数すべてに対してエラーが出ているようなのですが、
どのようにすればコンパイルできるようになるのしょうか?
教えていただければ幸いです。

エラーメッセージ:
CMakeFiles/points_and_lines.dir/src/points_and_lines.cpp.o: 関数 main' 内: points_and_lines.cpp:(.text+0x7e2):cvCreateCameraCapture’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0x834): cvSetCaptureProperty' に対する定義されていない参照です points_and_lines.cpp:(.text+0x850):cvSetCaptureProperty’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0x85f): cvNamedWindow' に対する定義されていない参照です points_and_lines.cpp:(.text+0x873):cvMoveWindow’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0x882): cvNamedWindow' に対する定義されていない参照です points_and_lines.cpp:(.text+0x896):cvMoveWindow’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0x8bd): cvCreateImage' に対する定義されていない参照です points_and_lines.cpp:(.text+0x8e2):cvMoveWindow’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0x909): cvCreateImage' に対する定義されていない参照です points_and_lines.cpp:(.text+0x91f):cvQueryFrame’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xc11): cvCircle' に対する定義されていない参照です points_and_lines.cpp:(.text+0xcdc):cvCircle’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xcf0): cvShowImage' に対する定義されていない参照です points_and_lines.cpp:(.text+0xd04):cvShowImage’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xd22): cv::Mat::Mat(_IplImage const*, bool)' に対する定義されていない参照です points_and_lines.cpp:(.text+0xd72):cv::_OutputArray::_OutputArray(cv::Mat&)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xd8b): cv::_InputArray::_InputArray(cv::Mat const&)' に対する定義されていない参照です points_and_lines.cpp:(.text+0xddf):cv::resize(cv::_InputArray const&, cv::OutputArray const&, cv::Size, double, double, int)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xdf8): cv::_OutputArray::_OutputArray(cv::Mat&)' に対する定義されていない参照です points_and_lines.cpp:(.text+0xe11):cv::_InputArray::_InputArray(cv::Mat const&)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xe2f): cv::flip(cv::_InputArray const&, cv::_OutputArray const&, int)' に対する定義されていない参照です points_and_lines.cpp:(.text+0xe48):cv::_InputArray::_InputArray(cv::Mat const&)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xe8b): cv::imshow(std::string const&, cv::_InputArray const&)' に対する定義されていない参照です points_and_lines.cpp:(.text+0xec2):cv::_OutputArray::_OutputArray(cv::Mat&)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xedb): cv::_InputArray::_InputArray(cv::Mat const&)' に対する定義されていない参照です points_and_lines.cpp:(.text+0xf2d):cv::Canny(cv::_InputArray const&, cv::_OutputArray const&, double, double, int, bool)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xf46): cv::_OutputArray::_OutputArray(cv::Mat&)' に対する定義されていない参照です points_and_lines.cpp:(.text+0xf5f):cv::_InputArray::_InputArray(cv::Mat const&)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xf7f): cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int)' に対する定義されていない参照です points_and_lines.cpp:(.text+0xf98):cv::_InputArray::InputArray(cv::Mat const&)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0xfdb): cv::imshow(std::string const&, cv::_InputArray const&)' に対する定義されていない参照です points_and_lines.cpp:(.text+0x103a):cv::InputArray::InputArray(cv::Mat const&)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0x10a5): cv::HoughLinesP(cv::_InputArray const&, cv::_OutputArray const&, double, double, int, double, double)' に対する定義されていない参照です points_and_lines.cpp:(.text+0x1254):cv::line(cv::Mat&, cv::Point
, cv::Point
, cv::Scalar
const&, int, int, int)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0x1296): cv::_InputArray::_InputArray(cv::Mat const&)' に対する定義されていない参照です points_and_lines.cpp:(.text+0x12d9):cv::imshow(std::string const&, cv::_InputArray const&)’ に対する定義されていない参照です
points_and_lines.cpp:(.text+0x1301): cvWaitKey' に対する定義されていない参照です CMakeFiles/points_and_lines.dir/src/points_and_lines.cpp.o: 関数cv::Mat::~Mat()’ 内:
points_and_lines.cpp:(.text._ZN2cv3MatD2Ev[_ZN2cv3MatD5Ev]+0x39): cv::fastFree(void*)' に対する定義されていない参照です CMakeFiles/points_and_lines.dir/src/points_and_lines.cpp.o: 関数cv::Mat::operator=(cv::Mat const&)’ 内:
points_and_lines.cpp:(.text.ZN2cv3MataSERKS0[ZN2cv3MataSERKS0]+0x111): cv::Mat::copySize(cv::Mat const&)' に対する定義されていない参照です CMakeFiles/points_and_lines.dir/src/points_and_lines.cpp.o: 関数cv::Mat::release()’ 内:
points_and_lines.cpp:(.text._ZN2cv3Mat7releaseEv[_ZN2cv3Mat7releaseEv]+0x47): cv::Mat::deallocate()' に対する定義されていない参照です CMakeFiles/points_and_lines.dir/src/points_and_lines.cpp.o: 関数cv::_OutputArray::_OutputArray<cv::Vec<int, 4> >(std::vector<cv::Vec<int, 4>, std::allocator<cv::Vec<int, 4> > >&)’ 内:
points_and_lines.cpp:(.text._ZN2cv12_OutputArrayC2INS_3VecIiLi4EEEEERSt6vectorIT_SaIS5_EE[_ZN2cv12_OutputArrayC5INS_3VecIiLi4EEEEERSt6vectorIT_SaIS5_EE]+0x2a): vtable for cv::_OutputArray' に対する定義されていない参照です CMakeFiles/points_and_lines.dir/src/points_and_lines.cpp.o: 関数cv::_InputArray::_InputArray<cv::Vec<int, 4> >(std::vector<cv::Vec<int, 4>, std::allocator<cv::Vec<int, 4> > > const&)’ 内:
points_and_lines.cpp:(.text._ZN2cv11_InputArrayC2INS_3VecIiLi4EEEEERKSt6vectorIT_SaIS5_EE[_ZN2cv11_InputArrayC5INS_3VecIiLi4EEEEERKSt6vectorIT_SaIS5_EE]+0x17): `vtable for cv::_InputArray’ に対する定義されていない参照です
collect2: error: ld returned 1 exit status
make[2]: *** [/home/toshioito/catkin_ws/devel/lib/using_markers/points_and_lines] エラー 1
make[1]: *** [using_markers/CMakeFiles/points_and_lines.dir/all] エラー 2
make: *** [all] エラー 2
Invoking “make -j4 -l4” failed

//テストプログラム
#include “opencv2/imgproc/imgproc.hpp”
#include “opencv2/highgui/highgui.hpp”
#include “opencv2/imgproc/imgproc_c.h”
#include
#include <ctype.h>
#include <stdio.h>
#include <math.h>
#include <ros/ros.h>
#include <visualization_msgs/Marker.h>
#include

#define M_PI 3.14159265358979323846
#define V4L2_FRAME_BUF_SIZE (2 * 4096 * 4096)

using namespace cv;
using namespace std;
int main( int argc, char** argv )
{
ros::init(argc, argv, “points_and_lines”);
ros::NodeHandle n;
ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>(“visualization_marker”, 10);

ros::Rate r(30);

float f = 0.0;
while (ros::ok())
{
// %Tag(MARKER_INIT)%
visualization_msgs::Marker points, line_strip, line_list;
points.header.frame_id = line_strip.header.frame_id = line_list.header.frame_id = “/my_frame”;
points.header.stamp = line_strip.header.stamp = line_list.header.stamp = ros::Time::now();
points.ns = line_strip.ns = line_list.ns = “points_and_lines”;
points.action = line_strip.action = line_list.action = visualization_msgs::Marker::ADD;
points.pose.orientation.w = line_strip.pose.orientation.w = line_list.pose.orientation.w = 1.0;
// %EndTag(MARKER_INIT)%

// %Tag(ID)%
points.id = 0;
line_strip.id = 1;
line_list.id = 2;
// %EndTag(ID)%

// %Tag(TYPE)%
points.type = visualization_msgs::Marker::POINTS;
line_strip.type = visualization_msgs::Marker::LINE_STRIP;
line_list.type = visualization_msgs::Marker::LINE_LIST;
// %EndTag(TYPE)%

// %Tag(SCALE)%
// POINTS markers use x and y scale for width/height respectively
points.scale.x = 0.2;
points.scale.y = 0.2;

// LINE_STRIP/LINE_LIST markers use only the x component of scale, for the line width
line_strip.scale.x = 0.1;
line_list.scale.x = 0.1;

// %EndTag(SCALE)%

// %Tag(COLOR)%
// Points are green
points.color.g = 1.0f;
points.color.a = 1.0;

// Line strip is blue
line_strip.color.b = 1.0;
line_strip.color.a = 1.0;

// Line list is red
line_list.color.r = 1.0;
line_list.color.a = 1.0;

// %EndTag(COLOR)%

// %Tag(HELIX)%
// Create the vertices for the points and lines
for (uint32_t i = 0; i < 100; ++i)
{
float y = 5 * sin(f + i / 100.0f * 2 * M_PI);
float z = 5 * cos(f + i / 100.0f * 2 * M_PI);

  geometry_msgs::Point p;
  p.x = (int32_t)i - 50;
  p.y = y;
  p.z = z;

  points.points.push_back(p);
  line_strip.points.push_back(p);

  // The line list needs two points for each line
  line_list.points.push_back(p);
  p.z += 1.0;
  line_list.points.push_back(p);
}

// %EndTag(HELIX)%

marker_pub.publish(points);
marker_pub.publish(line_strip);
marker_pub.publish(line_list);

r.sleep();

f += 0.04;

IplImage *src_img;
IplImage *tmp_img;
cv::Mat mat2,mat3,canny_img,out,cdst;
// カメラ解像度
// double w = 160, h = 120;
// double w = 320, h = 240;
int w = 1440, h = 1440;

// 中心座標(割合)
double ratio_cx1 = 0.472;
double ratio_cy1 = 0.51;

// 半径 r1:内円 r2:外円(割合)
double ratio_r1  = 0.140;
double ratio_r2  = 0.512;

// 分割数
int N = 24;

// 中心座標
int cx1 = ratio_cx1 * w + 0.5;
int cy1 = ratio_cy1 * h + 0.5;

// 半径 r1:内円 r2:外円
int r1  = ratio_r1  * h + 0.5;
int r2  = ratio_r2  * h + 0.5;

// 展開画像のサイズ
int w2 = 2 * r2 * M_PI + 0.5;
int h2 = (r2 - r1) + 0.5;

//
// カメラ初期化
//

CvCapture *capture =  cvCaptureFromCAM( 1 );
if (capture==NULL) {
	printf("Camera not found.\n");
	return 0;
}

cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_WIDTH,  w);
cvSetCaptureProperty (capture, CV_CAP_PROP_FRAME_HEIGHT, h);

//
// ウィンドウを作成する
//

// カメラ画像
cvNamedWindow( "CameraWindow", 0 );
//char *cameraWindow = "Camera";
cvMoveWindow( "CameraWindow", 700,500 );

// cvNamedWindow( cameraWindow, CV_WINDOW_AUTOSIZE );

// 展開画像
cvNamedWindow( "TenkaiWindow", 0 );
//char *tenkaiWindow = "Tenkai";
cvMoveWindow( "TenkaiWindow", 700,20 );

//cvNamedWindow(tenkaiWindow, CV_WINDOW_AUTOSIZE );
IplImage* imageWork = cvCreateImage(cvSize(w2, h2), IPL_DEPTH_8U, 3);
//IplImage* imageWorkg = cvCreateImage(cvSize(w2, h2), IPL_DEPTH_8U, 1);
int num = 0;
char mess[1024];
//二値化

cvMoveWindow( "canny", 700,800 );

// cvNamedWindow( cameraWindow, CV_WINDOW_AUTOSIZE );
IplImage* imagetmp = cvCreateImage(cvSize(w2, h2), IPL_DEPTH_8U, 1);

while (1) {
	// カメラから画像をキャプチャする
	IplImage *imageCamera = cvQueryFrame(capture);
	

	// 全方位画像を展開
	for (int dst_x=0; dst_x<w2; dst_x++) {
		for (int dst_y=0; dst_y<h2; dst_y++) {
	
			double t = 2* M_PI / w2 * dst_x - M_PI/2;
			double r = r1+(double)(r2-r1)/h2 * dst_y;
			int src_x = r * cos(t) + cx1 + 0.5;
			int src_y = r * sin(t) + cy1 + 0.5;

    		unsigned char *pSrc = (unsigned char *)(imageCamera->imageData + imageCamera->widthStep * src_y + src_x * 3);
    		unsigned char *pDst = (unsigned char *)(imageWork->imageData + imageWork->widthStep * (h2 - dst_y - 1) + dst_x * 3);
    	
    		*pDst = *pSrc;
    		*(pDst+1) = *(pSrc+1);
    		*(pDst+2) = *(pSrc+2);

		}
	}

	// 内円を描画
	cvCircle(imageCamera, cvPoint(cx1, cy1), (int)r1, CV_RGB(255, 255, 255), 1, 8, 0);

	// 外円を描画
	cvCircle(imageCamera, cvPoint(cx1, cy1), (int)r2, CV_RGB(255, 255, 255), 1, 8, 0);



    // カメラウィンドウに画像を表示する
    cvShowImage("CameraWindow", imageCamera);
	
    // 変換後ウィンドウに画像を表示する
    cvShowImage("TenkaiWindow", imageWork);

mat2 = imageWork; //(2)ポインタの代入
resize(mat2,mat2,cv::Size(),0.25,0.25);
cv::flip(mat2,mat3,0);
cv::imshow(“tenkaimat”, mat3);//画像を表示.
Canny(mat3,canny_img,50,200);
//cv::imshow(“edge”, canny_img);//画像を表示.
//cv::Sobel(canny_img,out,CV_8U,0,1);
cvtColor(canny_img, cdst, CV_GRAY2BGR);
cv::imshow(“vertical_edge”, canny_img);//画像を表示.

vector lines;
HoughLinesP(canny_img, lines, 1, CV_PI/180, 3, 15, 10 );
for( size_t i = 0; i < lines.size(); i++ )
{
Vec4i l = lines[i];
if((abs(l[0]-l[2])<7)&&(abs(l[1]-l[3])>32)){
line( cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0,0,255), 3, CV_AA);
}
}
imshow(“detected lines”, cdst);
cvWaitKey( 1 );

	// ファイル名
	sprintf(mess, "NUM : %06d", num);
	printf("%s\n", mess);
	
	// ファイルに保存する

// cvSaveImage(fname, frame, NULL);

// sleep(5);
num++;
}

cvReleaseImage(&src_img);
cvReleaseCapture(&capture);
cvDestroyAllWindows();

return 0;

}
}


#2

CMakeLists.txtの中にtarget_link_library()の部分に${OpenCV_LIBS}を追加されてみてはいかがでしょう?
インクルードまではできていてリンクで失敗している状況かと思われます。
参考までに自分が開発しているOpenCVを使ったROSノードのCMakeLists.txtのURLを貼っておきます。
こちらの83行目等のようにされてみてはいかがでしょうか??
開発の関係でもしご覧になった時に行数がずれてたらすみません・・・


#3

hakuturu583様
ご返事ありがとうございます。

ご指摘の通りtarget_link_librariesに${OpenCV_LIBRARIES}を追加しただけではコンパイルが進まなかったのですが

添付されていたCMakeLists.txtを参考にさせていただきfind_package(OpenCV REQUIRED)
を追加したところ無事にコンパイルできました。
本当に助かりました!!