大派键中怎么找不与派键p轨道成键平行的

opencv(17)
图像处理(23)
1. 边界处理的类型
2. opencv的实现
在图像处理中,经常需要空域或频域的滤波处理,在进入真正的处理程序前,需要考虑图像边界情况。
通常的处理方法是为图像增加一定的边缘,以适应 卷积核 在原图像边界的操作。
1. 增加边界的类型有以下4个类型:
以一行图像数据为例,abcdefgh是原图数据,|是图像边界,为原图加边
aaaaaa|abcdefgh|hhhhhhh & & 重复
fedcba|abcdefgh|hgfedcb & &反射
gfedcb|abcdefgh|gfedcba &反射101,相当于上一行的左右互换
cdefgh|abcdefgh|abcdefg &外包装
iiiiii|abcdefgh|iiiiiii &with some specified 'i' &常量
2. opencv的实现
opencv中有几处增加边界的实现,其源码分别散布在Utils.cpp,Filter.cpp,Ts_func.cpp中,功能和实现都基本相同。
以Utils的copyMakeBorder,及Filter中的borderInterpolate为例,这两种的代码风格比较通俗易懂。
边界处理的步骤:
& &首先,为目的图像(结果图像)分配内存,图像大小为size(src.rows + top + bottom, src.cols + left + right)
& & 然后,以原图为基准,逐行处理,先扩展左边界,复制原图数据到目的图像,再扩展右边界。
& & 最后,扩展上边界,以及下边界。
其中,每扩展一个边界像素,都需要计算出对应的原图中的位置,这个功能被提炼出来,就是borderInterpolate
&&&&&&&&&&int&cv::borderInterpolate(&int&p,&int&len,&int&borderType&)&&&{&&&&&&if(&(unsigned)p&&&(unsigned)len&)&&&&&&&&&&&&&&&;&&&&&&else&if(&borderType&==&BORDER_REPLICATE&)&&&&&&&&&&&p&=&p&&&0&?&0&:&len&-&1;&&&&&&else&if(&borderType&==&BORDER_REFLECT&||&borderType&==&BORDER_REFLECT_101&)&&&&&&&{&&&&&&&&&&int&delta&=&borderType&==&BORDER_REFLECT_101;&&&&&&&&&&if(&len&==&1&)&&&&&&&&&&&&&&return&0;&&&&&&&&&&do&&&&&&&&&&{&&&&&&&&&&&&&&if(&p&&&0&)&&&&&&&&&&&&&&&&&&&&&&p&=&-p&-&1&+&&&&&&&&&&&&&&&else&&&&&&&&&&&&&&&&&&p&=&len&-&1&-&(p&-&len)&-&&&&&&&&&&&}&&&&&&&&&&while(&(unsigned)p&&=&(unsigned)len&);&&&&&&}&&&&&&else&if(&borderType&==&BORDER_WRAP&)&&&&&&&&{&&&&&&&&&&if(&p&&&0&)&&&&&&&&&&&&&&&&p&-=&((p-len+1)/len)*&&&&&&&&&&if(&p&&=&len&)&&&&&&&&&&&&&&&&p&%=&&&&&&&}&&&&&&else&if(&borderType&==&BORDER_CONSTANT&)&&&&&&&&&&&&p&=&-1;&&&&&&else&&&&&&&&&&CV_Error(&CV_StsBadArg,&&Unknown/unsupported&border&type&&);&&&&&&return&p;&&}&&
非常量类型边界扩展:
static&void&copyMakeBorder_8u(&const&uchar*&src,&size_t&srcstep,&Size&srcroi,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uchar*&dst,&size_t&dststep,&Size&dstroi,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&top,&int&left,&int&cn,&int&borderType&)&&{&&&&&&const&int&isz&=&(int)sizeof(int);&&&&&&int&i,&j,&k,&elemSize&=&1;&&&&&&bool&intMode&=&false;&&&&&&&&if(&(cn&|&srcstep&|&dststep&|&(size_t)src&|&(size_t)dst)&%&isz&==&0&)&&&&&&{&&&&&&&&&&cn&/=&&&&&&&&&&&elemSize&=&&&&&&&&&&&intMode&=&true;&&&&&&}&&&&&&&&AutoBuffer&int&&_tab((dstroi.width&-&srcroi.width)*cn);&&&&&&&&int*&tab&=&_&&&&&&int&right&=&dstroi.width&-&srcroi.width&-&&&&&&&int&bottom&=&dstroi.height&-&srcroi.height&-&&&&&&&&&&&&&for(&i&=&0;&i&&&&i++&)&&&&&&&{&&&&&&&&&&j&=&borderInterpolate(i&-&left,&srcroi.width,&borderType)*&&&&&&&&&&&&for(&k&=&0;&k&&&&k++&)&&&&&&&&&&&&&&&&tab[i*cn&+&k]&=&j&+&k;&&&&&&}&&&&&&&&&&&&for(&i&=&0;&i&&&&i++&)&&&&&&&&{&&&&&&&&&&j&=&borderInterpolate(srcroi.width&+&i,&srcroi.width,&borderType)*&&&&&&&&&&for(&k&=&0;&k&&&&k++&)&&&&&&&&&&&&&&tab[(i+left)*cn&+&k]&=&j&+&k;&&&&&&}&&&&&&&&srcroi.width&*=&&&&&&&dstroi.width&*=&&&&&&&left&*=&&&&&&&right&*=&&&&&&&&&&&&&uchar*&dstInner&=&dst&+&dststep*top&+&left*elemS&&&&&&&&for(&i&=&0;&i&&&srcroi.&i++,&dstInner&+=&dststep,&src&+=&srcstep&)&&&&&&&{&&&&&&&&&&if(&dstInner&!=&src&)&&&&&&&&&&&&&&memcpy(dstInner,&src,&srcroi.width*elemSize);&&&&&&&&&&&&&&&&&&&&if(&intMode&)&&&&&&&&&&{&&&&&&&&&&&&&&const&int*&isrc&=&(int*)&&&&&&&&&&&&&&int*&idstInner&=&(int*)dstI&&&&&&&&&&&&&&for(&j&=&0;&j&&&&j++&)&&&&&&&&&&&&&&&&&&idstInner[j&-&left]&=&isrc[tab[j]];&&&&&&&&&&&&&&for(&j&=&0;&j&&&&j++&)&&&&&&&&&&&&&&&&&&idstInner[j&+&srcroi.width]&=&isrc[tab[j&+&left]];&&&&&&&&&&}&&&&&&&&&&else&&&&&&&&&&{&&&&&&&&&&&&&&for(&j&=&0;&j&&&&j++&)&&&&&&&&&&&&&&&&&&dstInner[j&-&left]&=&src[tab[j]];&&&&&&&&&&&&&&for(&j&=&0;&j&&&&j++&)&&&&&&&&&&&&&&&&&&dstInner[j&+&srcroi.width]&=&src[tab[j&+&left]];&&&&&&&&&&}&&&&&&}&&&&&&&&&&&&dstroi.width&*=&elemS&&&&&&dst&+=&dststep*&&&&&&&&&&&&for(&i&=&0;&i&&&&i++&)&&&&&&&&{&&&&&&&&&&j&=&borderInterpolate(i&-&top,&srcroi.height,&borderType);&&&&&&&&&&memcpy(dst&+&(i&-&top)*dststep,&dst&+&j*dststep,&dstroi.width);&&&&&&&}&&&&&&&&&&&&for(&i&=&0;&i&&&&i++&)&&&&&&&{&&&&&&&&&&j&=&borderInterpolate(i&+&srcroi.height,&srcroi.height,&borderType);&&&&&&&&&&memcpy(dst&+&(i&+&srcroi.height)*dststep,&dst&+&j*dststep,&dstroi.width);&&&&&&&}&&}&&
常量类型的扩展就更简单了:
static&void&copyMakeConstBorder_8u(&const&uchar*&src,&size_t&srcstep,&Size&srcroi,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&uchar*&dst,&size_t&dststep,&Size&dstroi,&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&int&top,&int&left,&int&cn,&const&uchar*&value&)&&{&&&&&&int&i,&j;&&&&&&AutoBuffer&uchar&&_constBuf(dstroi.width*cn);&&&&&&uchar*&constBuf&=&_constB&&&&&&int&right&=&dstroi.width&-&srcroi.width&-&&&&&&&int&bottom&=&dstroi.height&-&srcroi.height&-&&&&&&&&&&&&&for(&i&=&0;&i&&&dstroi.&i++&)&&&&&&&{&&&&&&&&&&for(&j&=&0;&j&&&&j++&)&&&&&&&&&&&&&&constBuf[i*cn&+&j]&=&value[j];&&&&&&}&&&&&&&&&&&&srcroi.width&*=&&&&&&&dstroi.width&*=&&&&&&&left&*=&&&&&&&right&*=&&&&&&&&&&&&&uchar*&dstInner&=&dst&+&dststep*top&+&&&&&&&&&&&&&for(&i&=&0;&i&&&srcroi.&i++,&dstInner&+=&dststep,&src&+=&srcstep&)&&&&&&&{&&&&&&&&&&if(&dstInner&!=&src&)&&&&&&&&&&&&&&memcpy(&dstInner,&src,&srcroi.width&);&&&&&&&&&&memcpy(&dstInner&-&left,&constBuf,&left&);&&&&&&&&&&memcpy(&dstInner&+&srcroi.width,&constBuf,&right&);&&&&&&}&&&&&&&&&&&&dst&+=&dststep*&&&&&&&&&&&&for(&i&=&0;&i&&&&i++&)&&&&&&&&&&memcpy(dst&+&(i&-&top)*dststep,&constBuf,&dstroi.width);&&&&&&&&&&&&&for(&i&=&0;&i&&&&i++&)&&&&&&&&&&&memcpy(dst&+&(i&+&srcroi.height)*dststep,&constBuf,&dstroi.width);&&}&&
对于medianBlur( InputArray _src0, OutputArray _dst, int ksize )的边界扩展方式是 重复复制最边缘像素 BORDER_REPLICATE。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:26587次
积分:1016
积分:1016
排名:千里之外
原创:61篇
转载:76篇
(23)(3)(13)(10)(17)(3)(7)(6)(4)(5)(6)(4)(1)(1)(1)(2)(7)(1)(4)(2)(4)(12)(2)(1)(5)1688人阅读
课题需要,前段时间一直在研究鸟瞰图,因为当摄像机和目标物有一个倾斜角的时候,采集到的图像会有一个透视畸变,而我们做图像处理,需要得到的是感兴趣部分的正视图,如下面两幅图所示。而我发现,鸟瞰图实现不了我想要的功能,因为我只需要感兴趣部分就可以了。后来发现,采用透视变换和透视矫正,可以很好的实现这个功能。下面详细地介绍了这个方法。
原文网址:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&
具体流程为:
a)载入图像→灰度化→边缘处理得到边缘图像(edge map)
cv::Mat im = cv::imread(filename);
cvtColor(im,gray,CV_BGR2GRAY);
Canny(gray,gray,100,150,3);
b)霍夫变换进行直线检测,此处使用的是probabilistic Hough transform(cv::HoughLinesP)而不是standard Hough transform(cv::HoughLines)
std::vector&Vec4i&
cv::HoughLinesP(gray,lines,1,CV_PI/180,70,30,10);
for(int i = 0; i & lines.size(); i++)
&&& line(im,cv::Point(lines[i][0],lines[i][1]),cv::Point(lines[i][2],lines[i][3]),Scalar(255,0,0),2,8,0);
c)通过上面的图我们可以看出,通过霍夫变换检测到的直线并没有将整个边缘包含,但是我们要求的是四个顶点所以并不一定要直线真正的相交,下面就要求四个顶点的坐标,公式为:
cv::Point2f
computeIntersect(cv::Vec4i a, cv::Vec4i b)
&&&&int&x1
= a[0], y1 = a[1], x2 = a[2], y2 = a[3];
&&&&int&x3
= b[0], y3 = b[1], x4 = b[2], y4 = b[3];
&&&&if&(float&d
= ((float)(x1-x2)
* (y3-y4)) - ((y1-y2) * (x3-x4)))
&&&&&&&&cv::Point2f
&&&&&&&&pt.x
= ((x1*y2 - y1*x2) * (x3-x4) - (x1-x2) * (x3*y4 - y3*x4)) /
&&&&&&&&pt.y
= ((x1*y2 - y1*x2) * (y3-y4) - (y1-y2) * (x3*y4 - y3*x4)) /
&&&&&&&&return&
&&&&&&&&return&cv::Point2f(-1,
std::vector&cv::Point2f&
for&(int&i
= 0; i & lines.size(); i++)
&&&&for&(int&j
= i+1; j & lines.size(); j++)
&&&&&&&&cv::Point2f
pt = computeIntersect(lines[i], lines[j]);
&&&&&&&&if&(pt.x
&= 0 && pt.y &= 0)
&&&&&&&&&&&&corners.push_back(pt);
d)检查是不是四边形
std::vector&cv::Point2f&
cv::approxPolyDP(cv::Mat(corners),
&&&&&&&&&&&&&&&&&cv::arcLength(cv::Mat(corners),&true)
* 0.02,&true);
if&(approx.size()
&&&&std::cout
object is not quadrilateral!&&&&
&&&&return&-1;
e)确定四个顶点的具体位置(top-left, bottom-left, top-right, and bottom-right corner)→通过四个顶点求出映射矩阵来.
void&sortCorners(std::vector&cv::Point2f&&
corners, cv::Point2f center)
&&&&std::vector&cv::Point2f&
&&&&for&(int&i
= 0; i & corners.size(); i++)
&&&&&&&&if&(corners[i].y
& center.y)
&&&&&&&&&&&&top.push_back(corners[i]);
&&&&&&&&else
&&&&&&&&&&&&bot.push_back(corners[i]);
&&&&cv::Point2f
tl = top[0].x & top[1].x ? top[1] : top[0];
&&&&cv::Point2f
tr = top[0].x & top[1].x ? top[0] : top[1];
&&&&cv::Point2f
bl = bot[0].x & bot[1].x ? bot[1] : bot[0];
&&&&cv::Point2f
br = bot[0].x & bot[1].x ? bot[0] : bot[1];
&&&&corners.clear();
&&&&corners.push_back(tl);
&&&&corners.push_back(tr);
&&&&corners.push_back(br);
&&&&corners.push_back(bl);
 下面是获得中心点坐标然后利用上面的函数确定四个顶点的坐标
for&(int&i
= 0; i & corners.size(); i++)
&&&&center
+= corners[i];
*= (1. / corners.size());
sortCorners(corners,
 定义目的图像并初始化为0
quad = cv::Mat::zeros(300, 220, CV_8UC3);
 获取目的图像的四个顶点
std::vector&cv::Point2f&
dst.push_back(cv::Point2f(0,0));
dst.push_back(cv::Point2f(quad.cols,0));
dst.push_back(cv::Point2f(quad.cols,quad.rows));
dst.push_back(cv::Point2f(0,quad.rows));
 计算映射矩阵
transmtx = cv::getPerspectiveTransform(corners, quad_pts);
进行透视变换并显示结果
cv::warpPerspective(im,
quad, transmtx, quad.size());
cv::imshow(&quadrilateral&,
事实上,此方法采用了透视变换,将图像平面映射到了显示窗口所在的平面,另外,哪怕不采用霍夫变换直线拟合,只要能确定扑克牌四个点的像素坐标(比如鼠标事件),就可以求得单应性矩阵,完成变换。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1702次
排名:千里之外Kinect的深度图像处理
+-c++,图片处理image-processing,kinect-CodeGo.net
Kinect的深度图像处理
这是我的问题
Kinect的被安装在房间(天花板上)的顶部。然后我把Kinect的下面的人的深度图像。
跳什么,我得到的是下面的人的俯视图。
然后,我要提取的人民头上来计数的人数。
由于我的方式看到它,这个问题需要识别图像的局部区域的些许。但我coudn't找出路。
可一个人的方式来实现这一目标?
是否有OpenCV的函数来获取当地最低面积?
本文地址 :CodeGo.net/580362/
-------------------------------------------------------------------------------------------------------------------------
1. 你可以尝试寻找水援助转变局部极小。快速搜索提出了要尝试用OpenCV的这个样本编码目。
我会支持前台,后台的分离从动态的“前景”(人)的静态背景。
然后,一旦你在人民的点云/深度贴图,你可以将它们例如与区域生长(颜色填充)方法。这样你得到的计数或分居的人,你可以找到他们的最低点,如果你正在寻找首脑特别。
我会暨暨直截了当的阈值去远近的深度,使用操作和两个并找到在生成的图像的边缘。
它不是超级灵活暨那种你硬编码的深度范围(最低预期人类高度) CodeGo.net,但它很容易设置/调整和shouldn'be可选这是一个有点blur和侵蚀/扩展,以帮助改进了profile。
虽然它有更多比我解释,你可以在这里看到演示
而这里的基本的OpenCV与OpenNI:
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include &iostream&
int threshNear = 60;
int threshFar = 100;
int dilateAmt = 1;
int erodeAmt = 1;
int blurAmt = 1;
int blurPre = 1;
void on_trackbar(int, void*){}
int main( )
capture.open(CV_CAP_OPENNI);
if( !capture.isOpened() )
cout && "Can not open a capture object." &&
return -1;
cout && "ready" &&
vector&vector&Point& &
namedWindow("depth map");
createTrackbar( "amount dilate", "depth map", &dilateAmt,16, on_trackbar );
createTrackbar( "amount erode", "depth map", &erodeAmt,16, on_trackbar );
createTrackbar( "amount blur", "depth map", &blurAmt,16, on_trackbar );
createTrackbar( "blur pre", "depth map", &blurPre,1, on_trackbar );
createTrackbar( "threshold near", "depth map", &threshNear,255, on_trackbar );
createTrackbar( "threshold far", "depth map", &threshFar,255, on_trackbar );
Mat depthM
if( !capture.grab() )
cout && "Can not grab images." &&
return -1;
if( capture.retrieve( depthMap, CV_CAP_OPENNI_DEPTH_MAP ) )
const float scaleFactor = 0.05f;
M depthMap.convertTo( show, CV_8UC1, scaleFactor );
//threshold
Mat tnear,
show.copyTo(tnear);
show.copyTo(tfar);
threshold(tnear,tnear,threshNear,255,CV_THRESH_TOZERO);
threshold(tfar,tfar,threshFar,255,CV_THRESH_TOZERO_INV);
show = tnear &//or cvAnd(tnear,tfar,show,NULL); to join the two thresholded images
if(blurPre == 1) blur(show,show,Size(blurAmt+1,blurAmt+1));
M show.copyTo(cntr);
erode(cntr,cntr,Mat(),Point(-1,-1),erodeAmt);
if(blurPre == 0) blur(cntr,cntr,Size(blurAmt+1,blurAmt+1));
dilate(cntr,cntr,Mat(),Point(-1,-1),dilateAmt);
//compute and draw contours
findContours(cntr,contours,0,1);
drawContours(cntr,contours,-1,Scalar(192,0,0),2,3);
//optionally compute bounding box and circle to exclude small blobs(non human) or do further filtering,etc.
int numContours = contours.size();
vector&vector&Point& & contours_poly( numContours );
vector&Rect& boundRect( numContours );
vector&Point2f& centers( numContours );
vector&float& radii(numContours);
for(int i = 0; i & numC i++ ){
approxPolyDP( Mat(contours[i]), contours_poly[i], 3, true );
boundRect[i] = boundingRect( Mat(contours_poly[i]) );
minEnclosingCircle(contours_poly[i],centers[i],radii[i]);
rectangle( cntr, boundRect[i].tl(), boundRect[i].br(), Scalar(64), 2, 8, 0 );
circle(cntr,centers[i],radii[i],Scalar(192));
imshow( "depth map", show );
imshow( "contours", cntr );
if( waitKey( 30 ) == 27 )//exit on esc
即使你OpenNI抢流深度您仍然可以插入的深度图像分割成OpenCV的。此外,您还可以检测边框和圆形这可能有助于事情进一步过滤粗。说你是在安装程序的办公空间,可能你要避免柱,植株高大,货架等。您可以检查密封的border圆或边框的宽度/高度的比率。
本文标题 :Kinect的深度图像处理
本文地址 :CodeGo.net/580362/
Copyright (C) 2014 CodeGo.net1440人阅读
图像处理以及算法(21)
基本原理:
腐蚀操作要求有待处理的2D图像F(x,y)以及操作数矩阵(类似卷积操作中的Kernel矩阵),常见的
为3X3的操作数矩阵。二值图像腐蚀操作的数学定义如下:
1.&&&&&&假设X是二值图像中所有像素欧几里德坐标的集合,K为3X3的操作数矩阵
2.&&&&&& Kx表示操作数处理X的结果,x表示起始像素点
3.&&&&&&腐蚀操作K对X的所有像素点操作,Kx是X所有像素点的子集。
一个二值图像腐蚀的例子如下,操作数矩阵为3X3,起始点为中心像素点,前景像素表示为1,背
景像素表示为0.图示如下:
当操作数在像素矩阵上移动时,任何一个在操作数之下的输入像素为背景像素时,则设置中心像素
为背景像素0,否则中心像素[0,0]下的输入像素值不变。
完整程序:
#include &stdio.h&
#include &stdlib.h&
#include &math.h&
#include &cv.h&
#include &highgui.h&
void main()
&IplImage *src = cvLoadImage(&1.jpg&, CV_LOAD_IMAGE_GRAYSCALE);
&int i = 0;
&int j = 0;
&int n = 0;
&int m = 0;
&int threshold = 128;
&&exit(1);
&IplImage *dst = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
&IplImage *edge = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
&//cvSetZero(dst);
&cvCopyImage(src, dst);
&for(i = 0; i & src-& i++)
&&char *pSrc = src-&imageData + i * src-&widthS
&&for(j = 0; j & src-& j++)
&&&unsigned char temp = 0;
&&&temp = (unsigned char)(*(pSrc + j));
&&&if(temp & threshold)
&&&&temp = (unsigned char)255;
&&&&temp = 0;
&&&*(pSrc + j) = (unsigned char)
&cvNamedWindow(&src&);
&cvShowImage(&src&, src);
&for(i = 1; i & src-&height - 1; i++)
&&char *pSrc = src-&imageData + i * src-&widthS
&&char *pDst = dst-&imageData + i * dst-&widthS
&&for(j = 1; j & src-&width - 1; j++)
&&&for(n = -1; n &= 1; n++)
&&&&for(m = -1; m &= 1; m++)
&&&&&if(n == 0 && m == 0)
&&&&&&m++;
&&&&&unsigned char temp = 0;
&&&&&temp = (unsigned char)(*(pSrc + j + n * src-&widthStep + m));
&&&&&if(temp == 0)
&&&&&&*(pDst + j) = (unsigned char)0;
&&&&&&n = 5;
&&&&&&m = 5;
&cvNamedWindow(&dst&);
&cvShowImage(&dst&, dst);
&for(i = 0; i & src-& i++)
&&char *pSrc = src-&imageData + i * src-&widthS
&&char *pDst = dst-&imageData + i * dst-&widthS
&&char *pEdge = edge-&imageData + i * edge-&widthS
&&for(j = 0; j & src-& j++)
&&&int temp = 0;
&&&temp = (unsigned char)(*(pSrc + j) - *(pDst + j));//图像差
&&&if(temp & 128)
&&&&*(pEdge + j) = (unsigned char)255;
&&&&*(pEdge + j) = (unsigned char)0;
&cvNamedWindow(&edge&);
&cvShowImage(&edge&, edge);
&cvWaitKey(0);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:85325次
排名:千里之外
原创:12篇
转载:28篇
(1)(3)(6)(1)(2)(8)(5)(2)(12)&编译环境:
Microsoft Visual
C++ .NET 2008
OpenCV计算机图像视觉处理库
主要流程:
摄像头获取原始图像
指定迷宫图像的四个顶点,进行透视变换,得到俯视图
对变换后的迷宫图像进行二值化处理
指定入口和出口,计算最优路径
实时捕捉小车位置,与最优路径相比较,通过串口向小车发出调整指令
小车最终到达出口
3.3.1原始图像
利用OpenCV的cvQueryFrame函数从摄像头获取原始图像,效率不高,且受制于电脑性能和摄像头质量。
3.3.2透视变换
迷宫路线计算和小车位置判断都基于透视变换后的俯视图,OpenCV提供了透视变换的函数WarpPerspective,该函数按照指定变换矩阵进行变换,而变换矩阵由GetPerspectiveTransform从变换前后两个图像中的4个对应点计算出来。
小车实时调整
小车必处于迷宫的某一格,将其坐标转换成中心点坐标后,通过判断其x和y坐标与所要走的下一个结点的x和y坐标之间的关系即可知道小车接下来应该怎么走。于是只要根据这些信息来发出相应的指令。转向时,使小车每一次转90度,在车轮不打滑的情况下小车应该能成功转向。串口通讯通过调用Win32
API来完成。
连接并摆放好摄像头,连接好电脑与小车之间的USB转RS232线。
运行程序,屏幕上出现一个命令行窗口和一个摄像头图像采集窗口。
此时可根据所拍摄的图像调整迷宫和摄像头的位置。
用鼠标点击窗口中迷宫的四个角,顺序为:左上、右上、右下、左下,点完左上角按一下键盘上的数字1,点完右上角按2,以此类推,全部点完后按0,这时屏幕上出现第二个窗口,现实的是经过透视变换和二值化处理的迷宫俯视图。注意做这一步的时候不要将小车放在迷宫上,否则会为图像引入噪音。
在二值化窗口中用鼠标点击来指定入口,点击以后按i,点击指定出口,按o.
然后按p,这时出现第三个窗口,上面用绿色画出了最优路径。
按回车键,屏幕上出现第四个窗口。这时可以放上小车,在这个窗口中用鼠标圈定小车,即开始实时跟踪,小车将自动走到出口。

我要回帖

更多关于 p轨道成键 的文章

 

随机推荐