首页

文章

请教基于opencv的轮廓提取问题

发布网友 发布时间:2022-04-19 19:29

我来回答

1个回答

热心网友 时间:2022-05-22 01:31

先灰度化->二值化,弄成二值图,你就会提取了

给你个例子
C/C++ code

#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);

// 创建结构元素

IplConvKernel *element = cvCreateStructuringElementEx( 2, 2, 0, 0, CV_SHAPE_ELLIPSE,0);

//用该结构对源图象进行数学形态学的开操作后,估计背景亮度

cvErode(src,tmp,element,9);

//使用任意结构元素腐蚀图像

cvDilate(tmp,src_back, element,9);

//使用任意结构元素膨胀图像

}

IplImage *FindCountours(IplImage* src,IplImage *pContourImg)

{

CvMemStorage *storage = cvCreateMemStorage(0); //提取轮廓需要的储存容量为默认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; // 轮廓数量

//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;
年终会活动策划方案 深度解析:第一财经回放,探索财经新风向 逆水寒手游庄园怎么邀请好友同住 逆水寒手游 逆水寒不同区可以一起组队吗? 逆水寒手游 逆水寒怎么进入好友世界? 逆水寒手游 逆水寒怎么去别人的庄园? 使用puppeteer实现将htmll转成pdf 内卷时代下的前端技术-使用JavaScript在浏览器中生成PDF文档 【译】将HTML转为PDF的几种实现方案 变形金刚08动画怎么样 变形金刚08动画的问题 变形金刚08动画日语版剧情介绍 高分!换显卡nvidia控制面板被我卸了,重新安装显卡驱动后没了nvidia控... 我的nvidia控制面板被卸载了 怎么找回啊 卸载后 这个画面看着很奇怪_百 ... 李卓彬工作简历 林少明工作简历 广东工业职业技术学院怎么样 郑德涛任职简历 唐新桂个人简历 土地入股的定义 ups快递客服电话24小时 贷款记录在征信保留几年? 安徽徽商城有限公司公司简介 安徽省徽商集团新能源股份有限公司基本情况 安徽省徽商集团有限公司经营理念 2019哈尔滨煤气费怎么有税? 快手删除的作品如何恢复 体育理念体育理念 有关体育的格言和理念 什么是体育理念 万里挑一算彩礼还是见面礼 绿萝扦插多少天后发芽 绿萝扦插多久发芽 扦插绿萝多久发芽 炖牛排骨的做法和配料 网络诈骗定罪标准揭秘 “流水不争先”是什么意思? mc中钻石装备怎么做 为什么我的MC里的钻石块是这样的?我想要那种。是不是版本的问题?如果是... 带“偷儿”的诗句 “君不见巴丘古城如培塿”的出处是哪里 带“奈何”的诗句大全(229句) 里翁行()拼音版、注音及读音 带“不虑”的诗句 “鲁肃当年万人守”的出处是哪里 无尘防尘棚 进出口报关流程,越详细越好。谢谢大家指教。 双线桥不是看化合价升多少就标多少的吗?为什么CL2+2KI=2KCL+I2中I失... 出师表高锰酸钾有画面了吗 2021年幼儿园新学期致家长一封信 openCV 轮廓识别 c++ opencv轮廓检测 OpenCv怎么判断框住轮廓的两个矩形框是否平行,并... 如何利用OPENCV的matchShapes进行轮廓匹配 关于OPENCV轮廓的问题。 有没有能改变字体的软件? 下载什么软件?可以改字体。 有什么软件可以换整个手机的字体(我手机已root) 什么换字体软件字体多? 什么软件可以更换iphone字体 我想给手机换个字体,用什么软件好? 手机更换字体的软件,求推荐几个好的 怎样能改变手机的字体,可以下载什么软件? 手机换字体软件哪个好 什么软件可以更换字体. 手机换字体用什么软件? 苹果11换字体用哪个软件 苹果手机字体用烦了下载什么软件可以改变字体? 有哪个软件可以把字体变花样 换字体用什么软件最好? OPENCV怎么能在比较复杂的图像中找到想要的物体的... opencv中提取的轮廓怎么用 opencv 请问我提取了图像的轮廓之后,想求这个轮廓... opencv 填充大致轮廓 opencv实现图像轮廓提取并矢量化 opencv找外接矩形,找的轮廓偏小,怎么解决 使用OpenCV提取轮廓之后,如何进行矢量化,需要什... 在opencv我已经进行了图像的轮廓处理,怎么算的轮... opencv检测直线并得到角度 OpenCV相关问题:可以用轮廓图和原图得出用轮廓裁... opencv检测出的轮廓判断是不是圆椭圆 opencv 怎么取内轮廓的点集 我想实现内轮廓的每个... Opencv提取的轮廓怎么保存? opencv 轮廓的点到边界框的距离 iPhoneX手机底部扬声器没有信号是什么原因? 始祖鸟parka各款比较 始祖鸟被安踏收购后会影响始祖鸟的品牌吗? 始祖鸟冲锋衣的型号在哪个地方看 salomon和始祖鸟哪个好? 请问用始祖鸟的ALPHA SV JACKET冲锋衣加上THETA SV...
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com