前言:
今年有一个高等教育部主办,举办地在余姚的比赛,我们报了机械手解魔方的项目!其中的方案之一是用摄像头采集魔方的六面信息!为了最快的采集信息,决定使用两个摄像头顶角照射,一个摄像头读取三面信息,这样两个摄像头一次直接读取完!
其中最快的方法就是两个摄像头,顶角摆放,采集六面信息!
这其中,我有两种方案!1- 直接在倾斜面上颜色识别采集信息,在进行面矩阵转换;2-将倾斜面矫正回来,在进行颜色识别!在两种的综合尝试下,我们采用第二种!
我用的开发环境是 QT+OpenCV !
代码及解释:
cv::Mat colorhandle::getFrame_f(){
cv::Mat imageout;
if(!camera_f_stop){
capture_f>>frame_f;
// cv::blur(frame_f, imageout, cv::Size(2,2));
// cv::medianBlur(frame_f, imageout, 3);
imageout = frame_f;
return imageout;
}
}
以上是一个摄像头的图像帧获得,两个同理!
cv::Mat colorhandle::splitColor(cv::Mat tempIge){
char vr,vg,vb;
cv::Mat temp;
temp= cv::Mat(frame_f.size(),frame_f.type(),cv::Scalar::all(0));
for(int r=0;r<tempIge.rows;r++){
cv::Vec3b *pixVal = tempIge.ptr<cv::Vec3b>(r);
for(int c=0;c<tempIge.cols;c++){
vr = pixVal[c][2];
vb = pixVal[c][1];
vg = pixVal[c][0];
if(abs(vr-vb)>pix_val_gal || abs(vg-vb)>pix_val_gal){
temp.at<cv::Vec3b>(r,c)[2] =vr;
temp.at<cv::Vec3b>(r,c)[1] =vb;
temp.at<cv::Vec3b>(r,c)[0] =vg;
}
}
}
return temp;
}
这是一个简单的获取彩色图像的方法,可以获得面的信息!当然还有获取状况如下:
接下来就是进行面的矫正!这个地方很关键,有很多种的方法,我一开始用的是将线将边画出来,当然了我在软件里也是读取这一块的信息,向上面的就是三个面,也就是三个大块的信息!一下是我的摄像头图像 !这里是为了方便校准才显示的
接下来就是最最关键的地方了,我如何将每个块的信息转化出来呢?这就需要OpenCV的仿射变换了!
void colorhandle::mWrapHandle(cv::Mat imgGet,std::vector<cv::Point2f> vecPoint, cv::Mat partImgeOut){ //这里矫正图片区域
std::vector<cv::Point2f>quad_pts;
quad_pts.push_back(cv::Point2f(0,0));
quad_pts.push_back(cv::Point2f(partImgeOut.cols,0));
quad_pts.push_back(cv::Point2f(partImgeOut.cols,partImgeOut.rows));
quad_pts.push_back(cv::Point2f(0,partImgeOut.rows));
cv::Mat transmtx =cv::getPerspectiveTransform(vecPoint,quad_pts);;
cv::warpPerspective(imgGet,partImgeOut,transmtx,partImgeOut.size());
}
以上就是仿射变化了,它是依据点的四边形变换,不同的起点,带来的是不同旋转的效果,所以非常方便的就把面矫正成我想要的效果!
以上看出我是矫正的左下角的面,效果看上去还可以!!!!!
这样的操作六个面,就可以最快速读取魔方的信息!
给大家分享一下我的未完成的小界面 :
然而实际中,机械手当着了视线,所以,不得不换种方式来读取!但是还是要和大家分享一下我们的设计方案!
最后,我们的视觉方案,如下:点击打开链接
欢迎指点,互相学习!