软件环境:Qt5.5.1,msvc2012编译器,OpenCV2.4.9
处理图像:CCD相机采集的一个绿色光斑,背景色是黑色。
(PS:图像存在很多噪声,暂时不做处理)
目的:定位光斑所在位置,并裁剪。
将实现函数写在Qt一个按键上,点击按键调用函数;
1、代码分段解释:
IplImage* src = cvLoadImage("D:/1.bmp",-1);
cvSmooth(src,src,CV_BLUR,5,5,0,0); //均值滤波
cvSmooth(src,src,CV_MEDIAN,5,5,0,0); //中值滤波
cvSmooth(src,src,CV_GAUSSIAN,5,5,0,0); //维纳滤波
定位目标区域的核心算法是仅仅找出大绿斑图像轮廓线,黑色背景存在许多小绿斑,影响轮廓线的采集,三种常用的滤波全用上,效果可以。
2、对图像进行二值化处理,设定一个阈值25,绿色通道大于25的像素点设置为(0,255,0),绿色通道小于25的像素点设置为(0,0,0).
CvScalar s; //存放4个double值
for(int i=0;iheight;i++)
{
for(int j=0;jwidth;j++)
{
s = cvGet2D(src,i,j);
if(s.val[1]>25)
{
s.val[0] = 0;
s.val[1] = 255;
s.val[2] = 0;
}
else
{
s.val[0] = 0;
s.val[1] = 0;
s.val[2] = 0;
}
cvSet2D(src,i,j,s); //设置像素
}
}
处理后图像效果是这样滴:
3、
IplImage *dst_gray;
dst_gray = cvCreateImage(cvGetSize(src),8,1);
cvCvtColor(src,dst_gray,CV_BGR2GRAY);
CvMemStorage *storage = cvCreateMemStorage(0);
CvSeq* contours = 0;
cvFindContours(dst_gray,storage,&contours,sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE,cvPoint(0,0)); //找出轮廓
cvFindContours函数要求输入的图像是灰度图,将绿色光斑转为灰色光斑最后调用函数,找到图像轮廓。
4、
for(int i=0;itotal;i++) //遍历轮廓的坐标
{
CvPoint* p = CV_GET_SEQ_ELEM(CvPoint,contours,i);//指针指向轮廓点坐标
if(p->xx;
y0 = p->y;
}
if(p->yx;
y1 = p->y;
}
}
将轮廓点坐标取出来,遍历所有坐标,用类似冒泡法,提取圆轮廓左边边界坐标值,上边边界坐标值。
5、
int range = 2*(x1-x0);
cvNamedWindow("src",0); //1或者CV_WIMDOW_AUTOSIZE是图片本来大小,0是铺满屏幕
cvShowImage("src",src);
cvReleaseImage(&src); //释放内存
IplImage* dst = cvLoadImage("D:/1.bmp",-1); //原通道读取图片
cvSetImageROI(dst,cvRect(x0,y1,range,range));//设置源图像ROI
IplImage* img = cvCreateImage(cvSize(range,range),dst->depth,dst->nChannels);//创建目标图像
cvCopy(dst,img); //复制图像
cvReleaseImage(&dst);
cvNamedWindow("image",0); //1或者CV_WIMDOW_AUTOSIZE是图片本来大小,0是铺满屏幕
cvShowImage("image",img);
收尾工作计算要裁剪的矩形区域的坐标与边长,进行裁剪显示,最后注意IplImage容器不能自动释放内存,需要手动释放。
最后上结果图(圆斑不是很圆,不能正好裁剪).
6、完整代码还是得有的:
void MainWindow::on_pushButton_clicked() //The first button
{
// Mat src = imread("D:/1.bmp");
// int height = src.rows;
// int width = src.cols;
IplImage* src = cvLoadImage("D:/1.bmp",-1);
cvSmooth(src,src,CV_BLUR,5,5,0,0); //均值滤波
cvSmooth(src,src,CV_MEDIAN,5,5,0,0); //中值滤波
cvSmooth(src,src,CV_GAUSSIAN,5,5,0,0); //维纳滤波
CvScalar s; //存放4个double值
for(int i=0;iheight;i++)
{
for(int j=0;jwidth;j++)
{
s = cvGet2D(src,i,j);
if(s.val[1]>25)
{
s.val[0] = 0;
s.val[1] = 255;
s.val[2] = 0;
}
else
{
s.val[0] = 0;
s.val[1] = 0;
s.val[2] = 0;
}
cvSet2D(src,i,j,s); //设置像素
}
}
IplImage *dst_gray;
dst_gray = cvCreateImage(cvGetSize(src),8,1);
cvCvtColor(src,dst_gray,CV_BGR2GRAY);
CvMemStorage *storage = cvCreateMemStorage(0);
CvSeq* contours = 0;
cvFindContours(dst_gray,storage,&contours,sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE,cvPoint(0,0)); //找出轮廓
int x0=50000,y0,x1,y1=50000;
for(int i=0;itotal;i++) //遍历轮廓的坐标
{
CvPoint* p = CV_GET_SEQ_ELEM(CvPoint,contours,i);
if(p->xx;
y0 = p->y;
}
if(p->yx;
y1 = p->y;
}
}
// qDebug()<depth,dst->nChannels);//创建目标图像
cvCopy(dst,img); //复制图像
cvReleaseImage(&dst);
cvNamedWindow("image",0); //1或者CV_WIMDOW_AUTOSIZE是图片本来大小,0是铺满屏幕
cvShowImage("image",img);
// qDebug()<