1. 程式人生 > >[求助]OpenCV:識別四邊形的四個角點問題,待解決

[求助]OpenCV:識別四邊形的四個角點問題,待解決

矩形原影象見最下面。

思路是,採用L1、L2、L3和L4四條線,按照如圖所示方向依次掃過圖形,遇到角點停止,返回座標。

該方法只對部分規則的四邊形適用


問題是A和B點的識別程式通不過,請問問大家是怎麼回事,該如何解決?

原始碼如下:

// gangban.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include "highgui.h"
#include "cv.h"
#include "cxcore.h"


int _tmain(int argc, _TCHAR* argv[])
{
	using namespace std;

	IplImage* src = cvLoadImage("D:\\PERSONAL\\VC++\\OpenCV\\image\\gbfushi.jpg",1);//\\5.jpg
//	cvNamedWindow("gbfushi",0);// 0 按視窗比例滿視窗顯示; 1 按原比例顯示,和視窗大小無關
//	cvShowImage("gbfushi",src);


	//將src的RGB三個通道分別顯示  測試發現B的畫素差異最大
	IplImage* src_b = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
	IplImage* src_g = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
	IplImage* src_r = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
	cvSplit(src,src_b,src_g,src_r,NULL);


/******** 正式處理部分程式碼 B通道 灰度圖  ***********/
	//1 二值化
	IplImage* src_gray = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);//IPL_DEPTH_8U   unchar
	cvThreshold(src_b,src_gray,190,255,CV_THRESH_BINARY);
//	cvNamedWindow("src_gray",0);cvShowImage("src_gray",src_gray);

	//2 開運算
	IplImage* src_open = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
	IplConvKernel* element = 0;//腐蝕結構體變數
	element = cvCreateStructuringElementEx(3,3,2,2,CV_SHAPE_RECT,0);//3*3矩形  錨點(2,2 )
	cvMorphologyEx(src_gray,src_open,NULL,element,1);
	cvNamedWindow("src_open",0);cvShowImage("src_open",src_open);

	//3 邊界提取
	IplImage* src_canndy = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
	cvCanny(src_open,src_canndy,250,255,3);
	cvNamedWindow("src_canndy",0);
	cvShowImage("src_canndy",src_canndy);

	//4 畫內切矩形
	uchar* data;//指向src_open畫素值的指標
	data = (uchar*)src_open->imageData;
	int yy = 0,xx = 0;
	CvScalar color;//B G R
		color.val[0] = 0;
		color.val[1] = 0;
		color.val[2] = 0;

	//D 點座標獲取 
	for(int b=0 ; b<src_canndy->height && 0 == data[ yy*src_canndy->width + xx]; b++)
	{
		for(xx=0 ; xx<=b && 0 == data[yy*src_canndy->width + xx];xx++)
			yy = b - xx;
	}
	printf("1 D : xx = %d, yy = %d \n",xx,yy);
	CvPoint pointD = cvPoint(xx,yy);
		color.val[0] = 0;//B G R
		color.val[1] = 128;
		color.val[2] = 255;
	cvCircle(src,pointD,10,color,5,8,0); //yellow
	xx = 0;
	yy = 0;

	//C 點座標獲取
	for( int b = src_canndy->width ; b>=0 && 0 == data[ yy*src_canndy->width + xx]; b-- )
	{
		for(xx = src_canndy->width ; xx >= b && 0 == data[ yy*src_canndy->width + xx]; xx--)
			yy = xx - b;
	}
	printf("2 C : xx = %d, yy = %d \n",xx,yy);
	CvPoint pointC = cvPoint(xx,yy);
		color.val[0] = 0;//B G R
		color.val[1] = 0;
		color.val[2] = 255;
	cvCircle(src,pointC,10,color,5,8,0); //red
	xx = 0;
	yy = 0;

	//A 點座標獲取
	for( int b = src_canndy->height ; b>=0 
		&& 0 == data[ yy*src_canndy->width + xx]; b-- )
	{
		for( xx = 0 ; xx <= src_canndy->height - b && 0 == data[ yy*src_canndy->width + xx]; xx++)
			yy = xx + b;
	}
	printf("2 A : xx = %d, yy = %d \n",xx,yy);
	CvPoint pointA = cvPoint(xx,yy);
		color.val[0] = 255;//B G R
		color.val[1] = 0;
		color.val[2] = 0;
	cvCircle(src,pointA,20,color,10,8,0); //blue
	xx = 0;
	yy = 0;

/*	//B 點座標獲取
	for( int b = src_canndy->height + src_canndy->width ; b >= src_canndy->height && 0 == data[ yy*src_canndy->width + xx]; b-- )
	{
		for(xx = src_canndy->width ; xx >= b - src->height && 0 == data[ yy*src_canndy->width + xx]; xx--)
			yy = b - xx;
	}
	printf("4 B : xx = %d, yy = %d \n",xx,yy);
	CvPoint pointB = cvPoint(xx,yy);
		color.val[0] = 0;//B G R
		color.val[1] = 255;
		color.val[2] = 0;
	cvCircle(src,pointB,20,color,10,8,0); //green
*/


	cvNamedWindow("gbfushi",0);cvShowImage("gbfushi",src);
	
	printf("src_open->widthStep = %d\n",src_open->widthStep);
	

	cvWaitKey(0);
	cvReleaseImage(&src);
	cvReleaseImage(&src_b);cvReleaseImage(&src_g);cvReleaseImage(&src_r);
	cvReleaseImage(&src_gray);
	cvReleaseImage(&src_open);
	cvReleaseImage(&src_canndy);
	cvDestroyAllWindows();


	return 0;
}

處理所用原影象: