Sam*_*ong 5 c c++ opencv video-processing
我正在尝试使用基于Canny过滤器和轮廓查找功能的摄像机/网络摄像头来制作程序来检测任何形状的物体.这是我的计划:
int main( int argc, char** argv )
{
CvCapture *cam;
CvMoments moments;
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* contours = NULL;
CvSeq* contours2 = NULL;
CvPoint2D32f center;
int i;
cam=cvCaptureFromCAM(0);
if(cam==NULL){
fprintf(stderr,"Cannot find any camera. \n");
return -1;
}
while(1){
IplImage *img=cvQueryFrame(cam);
if(img==NULL){return -1;}
IplImage *src_gray= cvCreateImage( cvSize(img->width,img->height), 8, 1);
cvCvtColor( img, src_gray, CV_BGR2GRAY );
cvSmooth( src_gray, src_gray, CV_GAUSSIAN, 5, 11);
cvCanny(src_gray, src_gray, 70, 200, 3);
cvFindContours( src_gray, storage, &contours, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, cvPoint(0,0));
if(contours==NULL){ contours=contours2;}
contours2=contours;
cvMoments(contours, &moments, 1);
double m_00 = cvGetSpatialMoment( &moments, 0, 0 );
double m_10 = cvGetSpatialMoment( &moments, 1, 0 );
double m_01 = cvGetSpatialMoment( &moments, 0, 1 );
float gravityX = (m_10 / m_00)-150;
float gravityY = (m_01 / m_00)-150;
if(gravityY>=0&&gravityX>=0){
printf("center point=(%.f, %.f) \n",gravityX,gravityY); }
for (; contours != 0; contours = contours->h_next){
CvScalar color = CV_RGB(250,0,0);
cvDrawContours(img,contours,color,color,-1,-1, 8, cvPoint(0,0));
}
cvShowImage( "Input", img );
cvShowImage( "Contours", src_gray );
cvClearMemStorage(storage);
if(cvWaitKey(33)>=0) break;
}
cvDestroyWindow("Contours");
cvDestroyWindow("Source");
cvReleaseCapture(&cam);
}
Run Code Online (Sandbox Code Playgroud)
该程序将检测相机捕获的所有轮廓,并打印轮廓的平均坐标.我的问题是如何只过滤掉一个物体/轮廓,这样我就能得到更精确的(x,y)物体位置?如果可能,任何人都可以告诉我如何使用(x,y)坐标标记对象的中心?
提前致谢.干杯
p/s:对不起,我无法上传截图,但如果有什么帮助,这里是链接.
编辑:让我的问题更清楚:
我认为它可以很容易地解决.在轮廓检测之前,我会建议一些形态学操作.此外,我建议过滤"out"较小的元素,并将最大的元素作为图像中唯一的元素.
我建议:
过滤线(直线或曲线):你必须决定你自己认为"线"和"形状"之间的边界.假设您将厚度为5像素或更多的所有对象视为对象,而将小于5像素的对象视为对象.使用5x5正方形或3像素大小的钻石形状作为结构元素的形态开口将解决这个问题.
通常用于过滤掉小物体:如果物体具有任意形状,那么纯形态开口就不会这样做:你必须做一个代数开口.特殊类型的代数开口是区域开口:移除图像中具有小于给定阈值的(像素)区域的所有连通分量的操作.如果你有一个上限的规模无趣的对象,或下界上的大小有趣的,该值应作为阈值.你可以通过更大的形态开口获得类似的效果,但它不会那么灵活.
用于过滤除最大值之外的所有对象:听起来像将连接的组件从最小的组件移除到最大的组件应该起作用.尝试标记连接的组件.在二进制(黑白图像)上,此图像转换通过创建灰度图像,将背景标记为0(黑色)以及每个具有不同的增加灰度值的组件来工作.最后,每个对象的像素用不同的值标记.您现在可以只查看灰度直方图,找到像素最多的灰度值.将所有其他灰度级别设置为0(黑色),图像中剩下的唯一对象是最大的灰度级别.
这些建议是从最简单到最复杂的建议.不过,我认为OpenCV可以帮助解决这些问题.在OpenCV中实现形态侵蚀,扩张,打开和关闭.我认为您可能需要自己构建一个代数开放运算符(或者使用OpenCV基本形态学组合),但我确信OpenCV可以帮助您标记连接的组件并检查生成的灰度图像的直方图.
最后,当只剩下一个物体的像素时,可以进行Canny轮廓检测.
| 归档时间: |
|
| 查看次数: |
4069 次 |
| 最近记录: |