广告位API接口通信错误,查看德得广告获取帮助

中国零食网移动版

主页 > 生活动态 >

正方形的判定_ 方形人战斗剧场

最近一个项目用到了图像识别,之前从未接触过OpenCV,经过各种找教程,终于是搞懂了一些。

整个具体流程大概是获取图像-->图像二值化,灰度图(cvtColor)-->图像降噪(GaussianBlur)->轮廓识别(cvFindContours)-->形状判断。

大多数教程很专业,各种参数分析看不懂,经过各种搜索终于是搞懂了。

识别圆

在识别圆方面,OpenCV有内置的方法:霍夫圆变化:

HoughCircles(edges, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);

参数分析:

edges:灰度图像

circles:std::vector circles;数组,用来存储圆的坐标信息

CV_HOUGH_GRADIENT:Hough 变换方式,目前只支持CV_HOUGH_GRADIENT, which is basically 21HT, described in [Yuen03].默认用这个

1.5:累加器图像的分辨率,1的时候是与获取到的图像相同,1.5就是1.5倍

10:圆与圆的最小距离,两个圆心距离如果在范围内则被认定为1个圆

200:100-200两个参数选就够了

100:默认100,数值越低识别圆越不精确(圆的数量识别变多可能有个弧线就被识别是圆)

最后两个参数分别是识别 圆的最小,最大的面积。


矩形识别

矩形识别并没有内置方法,需要自己手写。

最主要的方法是二值化。通过二值化来调节识别的强度。

cvThreshold(tgray, gray, 75, 250, CV_THRESH_BINARY);

参数分析:

src:原始 数组(单通道 , 8-bit of 32-bit 浮点数)。

dst:输出数组,必须与 src 的类型一致,或者为 8-bit。

threshold:阈值

max_value:使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值。

threshold_type:阈值类型

threshold_type=CV_THRESH_BINARY:如果 src(x,y)>threshold ,dst(x,y) = max_value; 否则,dst(x,y)=0;

threshold_type=CV_THRESH_BINARY_INV:如果 src(x,y)>threshold,dst(x,y) = 0; 否则,dst(x,y) = max_value.

threshold_type=CV_THRESH_TRUNC:如果 src(x,y)>threshold,dst(x,y) = max_value; 否则dst(x,y) = src(x,y).

threshold_type=CV_THRESH_TOZERO:如果src(x,y)>threshold,dst(x,y) = src(x,y) ; 否则 dst(x,y) = 0。

threshold_type=CV_THRESH_TOZERO_INV:如果 src(x,y)>threshold,dst(x,y) = 0 ; 否则dst(x,y) = src(x,y).

效果图如下:

在矩形识别里面的二值化图:

圆识别:

源码:

#include   
#include   
#include 
#include
#include
#include 
#include 
#include
#include 
#pragma comment(lib,"ws2_32.lib")
#include
using namespace cv;
					//
					//函数功能:用向量来做COSα=两向量之积/两向量模的乘积求两条线段夹角
					//输入:   线段3个点坐标pt1,pt2,pt0,最后一个参数为公共点
					//输出:   线段夹角,单位为角度
					//
double angle(CvPoint* pt1, CvPoint* pt2, CvPoint* 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;
	double angle_line = (dx1*dx2 + dy1 * dy2) / sqrt((dx1*dx1 + dy1 * dy1)*(dx2*dx2 + dy2 * dy2) + 1e-10);//余弦值
	return acos(angle_line) * 180 / 3.141592653;
}
//
//函数功能:采用多边形检测,通过约束条件寻找矩形
//输入:   img 原图像
//          storage 存储
//          minarea,maxarea 检测矩形的最小/最大面积
//          minangle,maxangle 检测矩形边夹角范围,单位为角度
//输出:   矩形序列
//
CvSeq* findSquares4(IplImage* img, CvMemStorage* storage, int minarea, int maxarea, int minangle, int maxangle, int(&temp)[30])
{
	CvSeq* contours;//边缘
	int N = 6;  //阈值分级
	CvSize sz = cvSize(img->width & -2, img->height & -2);
	IplImage* timg = cvCloneImage(img);//拷贝一次img
	IplImage* gray = cvCreateImage(sz, 8, 1); //img灰度图
	IplImage* pyr = cvCreateImage(cvSize(sz.width / 2, sz.height / 2), 8, 3);  //金字塔滤波3通道图像中间变量
	IplImage* tgray = cvCreateImage(sz, 8, 1); ;
	CvSeq* result;
	double s, t;
	int sk = 0;
	CvSeq* squares = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), storage);
	cvSetImageROI(timg, cvRect(0, 0, sz.width, sz.height));
	//金字塔滤波 
	cvPyrDown(timg, pyr, 7);
	cvPyrUp(pyr, timg, 7);
	//在3个通道中寻找矩形 
	for (int c = 0; c < 3;="" c++)="" 对3个通道分别进行处理="" {="" cvsetimagecoi(timg,="" c="" +="" 1);="" cvcopy(timg,="" tgray,="" 0);="" 依次将bgr通道送入tgray="" for="" (int="" l="0;" l="">< n;="" l++)="" {="" 不同阈值下二值化="" cvthreshold(tgray,="" gray,="" 75,="" 250,="" cv_thresh_binary);="" cvshowimage("111",="" gray);="" cvfindcontours(gray,="" storage,="" &contours,="" sizeof(cvcontour),="" cv_retr_list,="" cv_chain_approx_simple,="" cvpoint(0,="" 0));="" while="" (contours)="" {="" 多边形逼近="" result="cvApproxPoly(contours," sizeof(cvcontour),="" storage,="" cv_poly_approx_dp,="" cvcontourperimeter(contours)*0.02,="" 0);="" 如果是凸四边形并且面积在范围内="" if="" (result-="">total == 4 && fabs(cvContourArea(result, CV_WHOLE_SEQ)) > minarea  && fabs(cvContourArea(result, CV_WHOLE_SEQ)) < maxarea="" &&="" cvcheckcontourconvexity(result))="" {="" s="0;" 判断每一条边="" for="" (int="" i="0;" i="">< 5;="" i++)="" {="" if="" (i="">= 2)
						{   //角度            
							t = fabs(angle((CvPoint*)cvGetSeqElem(result, i), (CvPoint*)cvGetSeqElem(result, i - 2), (CvPoint*)cvGetSeqElem(result, i - 1)));
							s = s > t ? s : t;
						}
					}
					//这里的S为直角判定条件 单位为角度
					if (s > minangle && s < maxangle)="" {="" for="" (int="" i="0;" i="">< 4;="" i++)="" cvseqpush(squares,="" (cvpoint*)cvgetseqelem(result,="" i));="" cvrect="" rect="cvBoundingRect(contours," 1);="" 获取矩形边界框="" cvpoint="" p1;="" p1="cvPoint(rect.x" +="" rect.width="" 2,="" rect.y="" +="" rect.height="" 2);="" 矩形中心坐标="" std::cout="">< "x:"="">< p1.x="">< "y:"="">< p1.y="">< std::endl;="" }="" }="" contours="contours-">h_next;
			}
		}
		std::cout <>< std::endl;="" temp[26]="sk;" sk="0;" }="" cvreleaseimage(&gray);="" cvreleaseimage(&pyr);="" cvreleaseimage(&tgray);="" cvreleaseimage(&timg);="" return="" squares;="" }="" 函数功能:画出所有矩形="" 输入:="" img="" 原图像="" squares="" 矩形序列="" wndname="" 窗口名称="" 输出:="" 图像中标记矩形="" void="" drawsquares(iplimage*="" img,="" cvseq*="" squares,="" const="" char*="" wndname)="" {="" cvseqreader="" reader;="" iplimage*="" cpy="cvCloneImage(img);" cvpoint="" pt[4];="" int="" i;="" cvstartreadseq(squares,="" &reader,="" 0);="" for="" (i="0;" i="">< squares-="">total; i += 4)
	{
		CvPoint* rect = pt;
		int count = 4;
		memcpy(pt, reader.ptr, squares->elem_size);
		CV_NEXT_SEQ_ELEM(squares->elem_size, reader);
		memcpy(pt + 1, reader.ptr, squares->elem_size);
		CV_NEXT_SEQ_ELEM(squares->elem_size, reader);
		memcpy(pt + 2, reader.ptr, squares->elem_size);
		CV_NEXT_SEQ_ELEM(squares->elem_size, reader);
		memcpy(pt + 3, reader.ptr, squares->elem_size);
		CV_NEXT_SEQ_ELEM(squares->elem_size, reader);
		//cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 );
		cvPolyLine(cpy, &rect, &count, 1, 1, CV_RGB(rand() & 255, rand() & 255, rand() & 255), 1, CV_AA, 0);//彩色绘制
	}
	cvShowImage("22", cpy);
	cvReleaseImage(&cpy);
}
void SendMessageOne()
{
	//开起摄像头
	VideoCapture capture;
	capture.open(0);
	Mat edges;  //定义转化的灰度图
	if (!capture.isOpened())
		namedWindow("【效果图】", CV_WINDOW_NORMAL);
	const char* winn = "1111";
	if (!capture.isOpened())
		//namedWindow(winn, CV_WINDOW_NORMAL);
		CvMemStorage* storage = 0;
	CvMemStorage* storage = 0;
	storage = cvCreateMemStorage(0);
	while (1)
	{
		int Y=0, J=0;
		Mat frame;
		capture >> frame;
		IplImage img0 = frame;
		//drawSquares(&img0, findSquares4(&img0, storage, 100, 2000, 80, 100, a), winn);
		//cvClearMemStorage(storage);  //清空存储
		Mat E = frame(Range(1, 320), Range(1, 240));
		cvtColor(frame, edges, CV_BGR2GRAY);
		//高斯滤波
		GaussianBlur(edges, edges, Size(7, 7), 2, 2);
		std::vector circles;//存储每个圆的位置信息
								   //霍夫圆
		HoughCircles(edges, circles, CV_HOUGH_GRADIENT, 1.5, 10, 100, 100, 0, 50);
		for (size_t i = 0; i < circles.size();="" i++)="" {="" point="" center(cvround(circles[i][0]),="" cvround(circles[i][1]));="" int="" radius="cvRound(circles[i][2]);" std::cout="">< "圆的x是"="">< circles[i][0]="">< "圆的y是"="">< circles[i][1]="">< std::="" endl;="" 绘制圆轮廓="" circle(frame,="" center,="" radius,="" scalar(155,="" 50,="" 255),="" 3,="" 8,="" 0);="" int="" r="">(cvRound(circles[i][1]), cvRound(circles[i][0]))[2];//R
			int G = frame.at(cvRound(circles[i][1]), cvRound(circles[i][0]))[1];//G
			int B = frame.at(cvRound(circles[i][1]), cvRound(circles[i][0]))[0];//B
			int num = R + G + B;
			std::cout < "圆心颜色是"="">< num="">< std::endl;="" }="" imshow("【效果图】",="" frame);="" waitkey(30);="" }="" }="" int="" main()="" {="" std::thread="" *a="new" std::thread(sendmessageone);="" a-="">join();
	return 0;
}

参考文档:

(责任编辑:admin)
    广告位API接口通信错误,查看德得广告获取帮助