上文目的为了求的运动物体的位置信息,但是在寻找轮廓时,发现轮廓并非我想要的轮廓发现了mode变量的影响。现在继续前面任务对某一图像来操作看看会有什么样的结果。
突然发现,主体图像的边缘出现了很多干扰的小点点。我该如何处理这些问题呢?
处理上述问题。
方案一:面积与目标面积相近的轮廓作为处理对象。
方案二:借助图像腐蚀、膨胀的办法去掉周边的小毛刺。关于腐蚀与膨胀的处理参见潜墨的文章(http://blog.csdn.net/poem_qianmo/article/details/23710721)。
腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。膨胀就是图像中的高亮部分进行膨胀,“领域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中的高亮部分被腐蚀,“领域被蚕食”,效果图拥有比原图更小的高亮区域。
//By pengjc2001 (http://blog.csdn.net/pengjc2001)
#include <opencv2/opencv.hpp>
#include <stdlib.h>
#include "imgproc.hpp"
#include "cxcore.h"
#include "cv.h"
#include "highgui.h"
double area = 0;
double perimeter = 0;
double position_x = 0;
double position_y = 0;
IplImage *colorImg = NULL; //载入的图像
IplImage *grayImg = NULL; //灰度图像
IplImage *binaryImg = NULL; //二值图像
IplImage *edgeImg = NULL; //边缘
IplImage *erodeImg = NULL; //腐蚀后的二值图
IplImage *dilateImg = NULL; //膨胀后的二值图
const char *pstrWindowsSrcTitle = "原图(http://blog.csdn.net/pengjc2001)";
const char *pstrWindowsGrayTitle = "灰度图(http://blog.csdn.net/pengjc2001)";
const char *pstrWindowsBinaryTitle = "二值图(http://blog.csdn.net/pengjc2001)";
const char *pstrWindowsErodeTitle = "腐蚀后的二值图(http://blog.csdn.net/pengjc2001)";
const char *pstrWindowsDilateTitle = "膨胀后的二值图(http://blog.csdn.net/pengjc2001)";
const char *pstrWindowsOutLineTitle = "轮廓图(http://blog.csdn.net/pengjc2001)";
const char *pstrWindowsErodeOutLineTitle = "腐蚀后的轮廓图(http://blog.csdn.net/pengjc2001)";
const char *pstrWindowsDilateOutLineTitle = "膨胀后的轮廓图(http://blog.csdn.net/pengjc2001)";
void Draw_Contours(IplImage *Img, const char *Title)
{
CvMemStorage *pcvMStorage = cvCreateMemStorage();
CvSeq *pcvSeq = NULL;
cvFindContours(Img, pcvMStorage, &pcvSeq, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0));
// 画轮廓图
IplImage *pOutlineImage = cvCreateImage(cvGetSize(colorImg), IPL_DEPTH_8U, 3);
int nLevels = 3;
// 填充成白色
cvRectangle(pOutlineImage, cvPoint(0, 0), cvPoint(pOutlineImage->width, pOutlineImage->height), CV_RGB(255, 255, 255), CV_FILLED);
cvDrawContours(pOutlineImage, pcvSeq, CV_RGB(255, 0, 0), CV_RGB(0, 0, 0), nLevels, 1);
// 显示轮廓图
cvNamedWindow(Title, CV_WINDOW_AUTOSIZE);
cvShowImage(Title, pOutlineImage);
CvSeq *pcvSeqInner = NULL;
int inner = 0;
int external = 0;
area = cvContourArea(pcvSeq);
perimeter = cvArcLength(pcvSeq);
for (; pcvSeq != NULL; pcvSeq = pcvSeq->h_next)
{
external++;
area = cvContourArea(pcvSeq);
perimeter = cvArcLength(pcvSeq);
CvMoments *moments = (CvMoments*)malloc(sizeof(CvMoments));
cvMoments(pcvSeq, moments, 1);
double moment10 = cvGetSpatialMoment(moments, 1, 0);
double moment01 = cvGetSpatialMoment(moments, 0, 1);
area = cvGetCentralMoment(moments, 0, 0);
position_x = moment10 / area;
position_y = moment01 / area;
printf("area:%f\t perimeter:%f\n", area, perimeter);
printf("position_x: %f\t position_y: %f\t ", position_x, position_y);
printf("external:%d\t inner = %d\t h_next\n", external, inner);
for (pcvSeqInner = pcvSeq->v_next; pcvSeqInner != NULL; pcvSeqInner = pcvSeqInner->h_next)
{
inner++;
double area = cvContourArea(pcvSeqInner);
double perimeter = cvArcLength(pcvSeqInner);
CvMoments *moments = (CvMoments*)malloc(sizeof(CvMoments));
cvMoments(pcvSeqInner, moments, 1);
double moment10 = cvGetSpatialMoment(moments, 1, 0);
double moment01 = cvGetSpatialMoment(moments, 0, 1);
area = cvGetCentralMoment(moments, 0, 0);
position_x = moment10 / area;
position_y = moment01 / area;
printf("area:%f\t perimeter:%f\t", area, perimeter);
printf("position_x: %f\t position_y: %f\t \n", position_x, position_y);
printf("external:%d\t inner = %d\t \n", external, inner);
}
}
cvWaitKey(10);
cvReleaseMemStorage(&pcvMStorage);
cvReleaseImage(&pOutlineImage);
}
int main(int argc, char** argv)
{
colorImg = cvLoadImage("E:\\Visual Studio 2013\\Projects\\position_area2\\image1.jpg");
// 显示原图
cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE);
cvShowImage(pstrWindowsSrcTitle, colorImg);
// 转为灰度图
grayImg = cvCreateImage(cvGetSize(colorImg), IPL_DEPTH_8U, 1);
cvCvtColor(colorImg, grayImg, CV_BGR2GRAY);
cvNamedWindow(pstrWindowsGrayTitle, CV_WINDOW_AUTOSIZE);
cvShowImage(pstrWindowsGrayTitle, grayImg);
// 转为二值图
binaryImg = cvCreateImage(cvGetSize(colorImg), IPL_DEPTH_8U, 1);
cvThreshold(grayImg, binaryImg, 250, 255, CV_THRESH_BINARY);
cvNamedWindow(pstrWindowsBinaryTitle, CV_WINDOW_AUTOSIZE);
cvShowImage(pstrWindowsBinaryTitle, binaryImg);
IplConvKernel *element = cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_RECT);
// 腐蚀操作
erodeImg = cvCreateImage(cvGetSize(colorImg), IPL_DEPTH_8U, 1);
cvErode(binaryImg, erodeImg, element, 2);
cvNamedWindow(pstrWindowsErodeTitle, CV_WINDOW_AUTOSIZE);
cvShowImage(pstrWindowsErodeTitle, erodeImg);
// 膨胀操作
dilateImg = cvCreateImage(cvGetSize(colorImg), IPL_DEPTH_8U, 1);
cvDilate(binaryImg, dilateImg, element, 1);
cvNamedWindow(pstrWindowsDilateTitle, CV_WINDOW_AUTOSIZE);
cvShowImage(pstrWindowsDilateTitle, dilateImg);
Draw_Contours(binaryImg, pstrWindowsOutLineTitle);
Draw_Contours(erodeImg, pstrWindowsErodeOutLineTitle);
Draw_Contours(dilateImg, pstrWindowsDilateOutLineTitle);
cvWaitKey(0);
cvDestroyWindow(pstrWindowsSrcTitle);
cvDestroyWindow(pstrWindowsOutLineTitle);
cvDestroyWindow(pstrWindowsGrayTitle);
cvDestroyWindow(pstrWindowsBinaryTitle);
cvReleaseImage(&colorImg);
cvReleaseImage(&grayImg);
cvReleaseImage(&binaryImg);
cvReleaseImage(&erodeImg);
cvReleaseImage(&dilateImg);
return 0;
}