at_nakai
2014年6月13日 13時47分
OpenCVで2つの直線の交点を検出するソースコードを作ったのでシェアします。
このソースコードの動作確認は、ATDE5にUSBカメラを接続して行なっています。 アルゴリズムの検証用途だったため、Armadilloでは動作確認していませんのでご注意ください。
下図は動作確認時のキャプチャです。
Makefile
CROSS_COMPILE ?= arm-linux-gnueabihf- CC = $(CROSS_COMPILE)cc CXX = $(CROSS_COMPILE)g++ CFLAGS = -Wall -O2 CXXFLAGS = -Wall -O2 EXEC = vertex OBJS = vertex.o LDLIBS := -lopencv_core -lopencv_highgui -lopencv_imgproc -lm all: $(EXEC) $(EXEC): $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS) romfs: $(ROMFSINST) /usr/bin/$(EXEC) clean: rm -f $(OBJS) $(EXEC)
vertex.cpp
// The "Vertex Detector" program. #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" #include <iostream> #include <math.h> #include <string.h> using namespace cv; using namespace std; const char* wndname = "Vertex Detection Demo"; // helper function: // finds a cosine of angle between vectors // from pt0->pt1 and from pt0->pt2 double angle_cos( Point pt1, Point pt2, Point pt0 ) { double dx1 = pt1.x - pt0.x; double dy1 = pt1.y - pt0.y; double dx2 = pt2.x - pt0.x; double dy2 = pt2.y - pt0.y; if (pt0 == pt1 || pt0 == pt2) return 1.0; return fabs(dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10); } int main(int argc, char *argv[]) { namedWindow( wndname, 1 ); vector<vector<Point> > squares; const string source = "/dev/video0"; VideoCapture inputVideo(CV_CAP_V4L2); if (!inputVideo.isOpened()) { cout << "Could not open the input video: " << source << endl; return -1; } Mat srcimg, dstimg, workimg; for(;;) { inputVideo >> srcimg; if (srcimg.empty()) break; dstimg = srcimg.clone(); cvtColor(srcimg, workimg, CV_BGR2GRAY); Canny(workimg, workimg, 50, 200, 3, true); vector<Vec4i> lines; HoughLinesP( workimg, lines, 1, CV_PI/180, 80, 30, 10 ); if (lines.size() >= 2) for( size_t i = 1; i < lines.size(); i++ ) { #define P1X lines[i - 1][0] #define P1Y lines[i - 1][1] #define P3X lines[i - 1][2] #define P3Y lines[i - 1][3] #define P2X lines[i - 0][0] #define P2Y lines[i - 0][1] #define P4X lines[i - 0][2] #define P4Y lines[i - 0][3] double s1, s2; s1 = ((P4X - P2X) * (P1Y - P2Y) - (P4Y - P2Y) * (P1X - P2X))/2; s2 = ((P4X - P2X) * (P2Y - P3Y) - (P4Y - P2Y) * (P2X - P3X))/2; Point v; v.x = P1X + (P3X - P1X) * s1 / (s1 + s2); v.y = P1Y + (P3Y - P1Y) * s1 / (s1 + s2); if (v.x < 0 || v.y < 0) continue; Point p1, p2; p1.x = P1X; p1.y = P1Y; p2.x = P2X; p2.y = P2Y; double cosine = angle_cos(p1, p2, v); if (cosine > 0.3) continue; line( dstimg, Point(lines[i - 1][0], lines[i - 1][1]), Point(lines[i - 1][2], lines[i - 1][3]), Scalar(255,0,0), 3, 8 ); line( dstimg, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), Scalar(0,0,255), 3, 8 ); cout << "(" << v.x << ", " << v.y << "), " << cosine << endl; cv::circle(dstimg, v, 10, Scalar(0, 255, 0), 3, 8); } imshow(wndname, dstimg); cvWaitKey(10); } return 0; }