OpenCV提取轮廓(去掉面积小的轮廓)
轉(zhuǎn)自:http://www.kaixuela.net/?p=23
?
#include <stdio.h>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include <iostream>
using namespace std;
#pragma comment(lib,"cv.lib")
#pragma comment(lib,"cxcore.lib")
#pragma comment(lib,"highgui.lib")
?
struct Position
{
??? int x,y;
};
?
double per[256];// 保存灰度概率
IplImage *FindCountours(IplImage* src,IplImage *pContourImg);
int ImageStretchByHistogram(IplImage *src,IplImage *dst);
IplImage* Hist_Equalization(IplImage *srcimg);
void proBorder(IplImage *src); // 邊界的處理
void GetBackImage(IplImage* src,IplImage* src_back);
void Threshold(IplImage *src);
int GetThreshold(double *const prob);
void Getprobability(IplImage *src);
double Eccentricity(IplImage *src);
?
void main()
{
??? //IplImage * src = cvLoadImage("C:\\image19\\A634.jpg",-1);//灰度圖的方式載入
??? IplImage * src = cvLoadImage("C:\\image19\\A857.jpg",-1);
??? IplImage * dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);
??? IplImage *src_back = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,src->nChannels);
??? GetBackImage(src,src_back);
??? dst = FindCountours(src_back,dst);
?
??? cvNamedWindow("test",CV_WINDOW_AUTOSIZE);
??? cvShowImage("test",dst);
??? cvWaitKey(0);
??? cvReleaseImage(&src);
??? cvReleaseImage(&dst);
}
?
void GetBackImage(IplImage* src,IplImage* src_back)
{
??? //cvCvtColor(src,src,CV_RGB2GRAY);//灰度化
??? IplImage *tmp = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,3);
??? // 創(chuàng)建結(jié)構(gòu)元素
??? IplConvKernel? *element = cvCreateStructuringElementEx( 2, 2, 0, 0, CV_SHAPE_ELLIPSE,0);
??? //用該結(jié)構(gòu)對源圖象進行數(shù)學(xué)形態(tài)學(xué)的開操作后,估計背景亮度
??? cvErode(src,tmp,element,9);
??? //使用任意結(jié)構(gòu)元素腐蝕圖像
??? cvDilate(tmp,src_back, element,9);
??? //使用任意結(jié)構(gòu)元素膨脹圖像
}
?
?
IplImage *FindCountours(IplImage* src,IplImage *pContourImg)
{
??? CvMemStorage *storage = cvCreateMemStorage(0); //提取輪廓需要的儲存容量為默認(rèn)KB
??? CvSeq * pcontour = 0;? //提取輪廓的序列指針
??? IplImage *temp = cvCreateImage(cvGetSize(src),src->depth,1);
?
??? //cvSmooth(src,temp,CV_GAUSSIAN,3,1,0);
?
??? cvSmooth(src,src,CV_GAUSSIAN,3,1,0);//平滑處理
??? cvCvtColor(src,temp,CV_RGB2GRAY);//灰度化
?
??? Getprobability(temp);
?
??? printf("最好的閾值:%d\n",GetThreshold(per));
?
??? //Threshold(temp);
?
??? proBorder(temp);
??? cvThreshold(temp,temp,GetThreshold(per),255,CV_THRESH_BINARY_INV);
?
??? int contoursNum = 0; // 輪廓數(shù)量
??? //int mode = CV_RETR_LIST;
??? int mode = CV_RETR_EXTERNAL;// 提取最外層輪廓
??? contoursNum = cvFindContours(temp,storage,&pcontour,sizeof(CvContour),mode,CV_CHAIN_APPROX_NONE);
??? // contoursNum = cvFindContours(temp,storage,&pcontour,sizeof(CvContour),CV_RETR_LIST,CV_CHAIN_APPROX_SIMPLE,cvPoint(0,0));
??? //二值圖, 得到輪廓存儲,輪廓指針序列,header_size,提取模式,逼近方法
?
??? CvScalar externalColor;// 保存顏色值
??? CvScalar holeColor;
??? //————–畫輪廓—————-//
??? for (; pcontour != 0; pcontour=pcontour -> h_next)
??? {
??????? //holeColor=CV_RGB(rand()&255,rand()&255,rand()&255);
??????? //externalColor=CV_RGB(rand()&255,rand()&255,rand()&255);
??????? CvRect r = ((CvContour *)pcontour)->rect;
??????? if(r.height * r.width < 800)
??????? {
??????????? holeColor=CV_RGB(0,0,0);
??????????? externalColor=CV_RGB(0,0,0);
??????????? cvDrawContours(pContourImg,pcontour,externalColor,holeColor,1,1,8);
??????? }
??????? else
??????? {
??????????? //取得輪廓面積
??????????? double contArea = fabs(cvContourArea(pcontour,CV_WHOLE_SEQ));
??????????? //取得輪廓長度
??????????? double contLenth = cvArcLength(pcontour,CV_WHOLE_SEQ,-1);
??????????? // 圓形度
??????????? double contcircularity = contLenth * contLenth / contArea;?
??????????? double pxl =Eccentricity(temp);
??????????? cout<<"面積為:"<<contArea<<endl;
??????????? cout<<"周長為:"<<contLenth<<endl;
??????????? cout<<"圓形度為:"<<contcircularity<<endl;
?
??????????? holeColor=CV_RGB(255,255,255);
??????????? externalColor=CV_RGB(255,255,255);
?
??????????? cvDrawContours(pContourImg,pcontour,externalColor,holeColor,1,1,8);
??????? }
??? }
??? //IplConvKernel? *element = cvCreateStructuringElementEx( 2, 2, 0, 0, CV_SHAPE_ELLIPSE,0);
??? //cvDilate(pContourImg,pContourImg, element,9);
??? return pContourImg;
?
}
?
double Eccentricity(IplImage *src)//偏心率
{
??? Position pos[4];
??? int width = src->width;
??? int height = src->height;
??? int i,j;
?
??? for(i = 0; i < height; i++)
??? {
??????? for(j = 0; j < width; j++)
??????? {
??????????? int pixel = (int)cvGet2D(src,i,j).val[0];
??????????? if(pixel != 0)
??????????? {
??????????????? pos[0].x = j;
??????????????? pos[0].y = i;//
??????????????? goto s;
??????????? }
??????? }
??? }
s:??
??? for(i = height – 1; i >= 0; i–)
??? {
??????? for(j = 0; j < width ; j++)
??????? {
??????????? int pixel = (int)cvGet2D(src,i,j).val[0];
??????????? if(pixel != 0)
??????????? {
??????????????? pos[1].x = j;
??????????????? pos[1].y = i;//
??????????????? goto w;
??????????? }
??????? }
??? }
w:
??? for(i = 0 ; i < width ; i++)
??? {
??????? for(j = 0;j < height; j++)
??????? {
??????????? int pixel = (int)cvGet2D(src,j,i).val[0];
??????????? if(pixel != 0)
??????????? {
??????????????? pos[2].x = j;//
??????????????? pos[2].y = i;
??????????????? goto e;
??????????? }
??????? }
??? }
e:
??? for(i = width – 1; i >= 0; i–)
??? {
??????? for(j = 0 ; j < height ; j++)
??????? {
??????????? int pixel = (int)cvGet2D(src,j,i).val[0];
??????????? if(pixel != 0)
??????????? {
??????????????? pos[3].x = j;//
??????????????? pos[3].y = i;
??????????????? goto f;
??????????? }
?
??????? }
??? }
?
f:
??? int l_dis = abs(pos[0].y – pos[1].y);
??? int s_dis = abs(pos[2].x – pos[3].x);
??? int tmp_dis;
??? if(l_dis > s_dis)
??? {
??????? printf("偏心率:%f\n",l_dis*1.0/s_dis);
??? }
??? else
??? {
??????? tmp_dis = l_dis;
??????? l_dis = s_dis;
??????? s_dis = tmp_dis;
??????? printf("偏心率:%f\n",l_dis*1.0/s_dis);
??? }
?
??? return 0;
}
?
void Getprobability(IplImage *src)
{
??? memset(per,0,sizeof(per));
??? int width = src->width;
??? int height = src->height;
??? for(int i = 0; i < height; i++) {
??????? for(int j = 0; j < width; j++) {
??????????? per[(int)cvGet2D(src,i,j).val[0]]++;
??????? }
??? }
??? int PixlNum = width * height;
??? for(i = 0; i < 256; i++)
??????? per[i] = per[i] / PixlNum;
?
}
?
int GetThreshold(double *const prob)
{
??? int threshold = 0;
??? double maxf = 0;
??? for (int crrctThrshld = 1; crrctThrshld < 256 – 1; ++crrctThrshld) {
??????? double W0 = 0, W1 = 0, U0 = 0, U1 = 0;
??????? int i = 0;
??????? for (i = 0; i <= crrctThrshld; ++i) {?
??????????? U0 += i * prob[i];
??????????? W0 += prob[i];
??????? }
??? ??? for (; i < 256; ++i) {
??????????? U1 += i * prob[i];
??????????? W1 += prob[i];
??????? }
??????? if (W1 == 0 || W1 == 0)
??????????? continue;
??????? U0 /= W0;
??????? U1 /= W1;
??????? double D0 = 0, D1= 0;
??????? for (i = 0; i <= crrctThrshld; ++i)?
??????????? D0 += pow((i – U0) * prob[i], 2.0);
??????? for (; i < 256; ++i)?
??????????? D1 += pow((i – U1) * prob[i], 2.0);
??????? D0 /= W0;
??????? D1 /= W1;
??????? double Dw = pow(D0, 2.0) * W0 + pow(D1, 2.0) * W1;
??????? double Db = W0 * W1 * pow((U1 – U0), 2.0);
??????? double f = Db / (Db + Dw);
??????? if (maxf < f) {
??????????? maxf = f;
??????????? threshold = crrctThrshld;
??????? }
??? }
??? return threshold;
}
?
void proBorder(IplImage *src) // 邊界的處理
{
??? int i,j;
??? int height = src->height;
??? int width = src->width;
?
??? int N = 100;
?
??? for(i = 0; i < N * width; i += width) // i表示向下走左上角
??? {
??????? for(j = 0; j < N ; j++)
??????? {
??? ??????? int index = i + j;
??????????? src->imageData[index] = (char)255;
??????? }
??? }
?
??? int NN = 150;
??? int sw = width * (height – NN);// 左下角 三角形
??? int? t = 1;
??? for(i = sw; i < sw + NN * width; i += width,t++)
??? {
??????? for(j = 0; j < t; j++)
??????? {
??????????? int index = i + j;
??????????? src->imageData[index] = (char)255;
??????? }
??? }
?
??? int se = (height – NN – 1) * width; // 右下角
??? t = 0;
??? for(i = se; i < width * height ; i += width,t++)
??? {
??????? for(j = 0; j < t; j++)
??????? {
??????????? int index = i + j – t;
??????????? src->imageData[index] = (char)255;
??????? }
??? }
?
??? int ne = width – NN;?????????????????? // 右上角 三角形剪切
??? t = 0;
??? for(i = ne; i < NN * width; i +=width,t++)
??? {
??????? for(j = 0; j < NN – t; j++)
??????? {
??????????? int index = i + j + t;
??????????? src->imageData[index] = (char)255;
??????? }
??? }
?
}
?
void Threshold(IplImage *src)
{
??? int width = src->width;
??? int height = src->height;
??? float minpixel = cvGet2D(src,0,0).val[0];
??? float maxpixel = cvGet2D(src,0,0).val[0];
??? CvScalar s;
??? for(int i = 0; i < height; i++){
??????? for(int j = 0; j < width; j++){
??????????? s = cvGet2D(src,i,j);
??????????? if(s.val[0] > maxpixel)
??? ??????????? maxpixel = s.val[0];
??????????? if(s.val[0] < minpixel)
??????????????? minpixel = s.val[0];
??????? }
??? }
??? float firstgrey = (maxpixel + minpixel) / 2;
??? printf("%f\n",firstgrey);
?
??? float lastgrey;
??? float sum1 = 0,sum2 = 0;
??? int num1 = 0,num2 = 0;
??? int result = 0;
??? while(1)
??? {
??????? result ++;
??????? for(i = 0; i < height; i++){
??????????? for(int j = 0; j < width; j++){
??????????????? s = cvGet2D(src,i,j);
??????????????? if(s.val[0] < firstgrey)
??????????????? {
??????????????????? sum1 += s.val[0];
??????????????????? num1++;
??????????????? }
??????????????? if(s.val[0] < firstgrey)
??????????????? {
??????????????????? sum2 += s.val[0];
??????????????????? num2++;
??????????????? }
??????????? }
??????? }
??????? lastgrey = (sum1/num1 + sum2/num2)/2;
?
??????? if((int)lastgrey == (int)firstgrey)
??????????? break;
??????? else
??????? {
??????????? firstgrey = lastgrey;
??????????? sum1 = sum2 = 0;
??????????? num1 = num2 = 0;
??????? }
??? }
?
??? lastgrey = (sum1/num1 + sum2/num2)/2;
??? printf("%f %d\n",firstgrey,result);
}
?
總結(jié)
以上是生活随笔為你收集整理的OpenCV提取轮廓(去掉面积小的轮廓)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows7下配置MinGW+Cod
- 下一篇: OpenCV中SVM的使用