opencv-图像二值化、阈值获取、直方图、轮廓提取
2012-08-25 20:29
417 查看
Code:
#include <cv.h>
#include <highgui.h>
#include <windows.h>
// 获取直方图
// 1. pImageData 图像数据
// 2. nWidth 图像宽度
// 3. nHeight 图像高度
// 4. nWidthStep 图像行大小
// 5. pHistogram 直方图
BOOL GetHistogram(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep,
int *pHistogram)
{
int i = 0;
int j = 0;
unsigned char *pLine = NULL;
// 清空直方图
memset(pHistogram, 0, sizeof(int) * 256);
for (pLine = pImageData, j = 0; j < nHeight; j++, pLine += nWidthStep)
{
for (i = 0; i < nWidth; i++)
{
pHistogram[pLine[i]]++;
}
}
return TRUE;
}
// 大津法取阈值
// 1. pImageData 图像数据
// 2. nWidth 图像宽度
// 3. nHeight 图像高度
// 4. nWidthStep 图像行大小
// 函数返回阈值
int Otsu(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep)
{
int i = 0;
int j = 0;
int nTotal = 0;
int nSum = 0;
int A = 0;
int B = 0;
double u = 0;
double v = 0;
double dVariance = 0;
double dMaximum = 0;
int nThreshold = 0;
int nHistogram[256];
// 获取直方图
GetHistogram(pImageData, nWidth, nHeight, nWidthStep, nHistogram);
for (i = 0; i < 256; i++)
{
nTotal += nHistogram[i];
nSum += (nHistogram[i] * i);
}
for (j = 0; j < 256; j++)
{
A = 0;
B = 0;
for (i = 0; i < j; i++)
{
A += nHistogram[i];
B += (nHistogram[i] * i);
}
if (A > 0)
{
u = B / A;
}
else
{
u = 0;
}
if (nTotal - A > 0)
{
v = (nSum - B) / (nTotal - A);
}
else
{
v = 0;
}
dVariance = A * (nTotal - A) * (u - v) * (u - v);
if (dVariance > dMaximum)
{
dMaximum = dVariance;
nThreshold = j;
}
}
return nThreshold;
}
// 二值化
// 1. pImageData 图像数据
// 2. nWidth 图像宽度
// 3. nHeight 图像高度
// 4. nWidthStep 图像行大小
// 5. nThreshold 阈值
BOOL Threshold(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep,
unsigned int nThreshold)
{
int i = 0;
int j = 0;
unsigned char *pLine = NULL;
for (pLine = pImageData, j = 0; j < nHeight; j++, pLine += nWidthStep)
{
for (i = 0; i < nWidth; i++)
{
if (pLine[i] >= nThreshold)
{
pLine[i] = 0x00;
}
else
{
pLine[i] = 0xff;
}
}
}
return TRUE;
}
// 二值化图像取反
void Not(IplImage *edge)
{
int i;
int j;
for(i=0;i<edge->height;i++)
for(j=0;j<edge->width;j++)
{
if(edge->imageData[edge->height*i+j]==0)
edge->imageData[edge->height*i+j]=1;
else
edge->imageData[edge->height*i+j]=0;
}
}
BOOL FindContours(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep)
{
int i = 0;
int j = 0;
unsigned char *pLine[3] = { NULL, NULL, NULL };
for (j = 1; j < nHeight - 1; j++)
{
pLine[0] = pImageData + nWidthStep * (j - 1);
pLine[1] = pImageData + nWidthStep * j;
pLine[2] = pImageData + nWidthStep * (j + 1);
for (i = 1; i < nWidth - 1; i++)
{
if (pLine[0][i-1] == 0xFF && pLine[0][i] == 0xFF && pLine[0][i+1] == 0xFF &&
pLine[1][i-1] == 0xFF && pLine[1][i] == 0xFF && pLine[1][i+1] == 0xFF &&
pLine[2][i-1] == 0xFF && pLine[2][i] == 0xFF && pLine[2][i+1] == 0xFF)
{
pLine[0][i-1] = 0;
}
else
{
pLine[0][i-1] = pLine[1][i];
}
}
}
return TRUE;
}
int main(int argc, char* argv[])
{
IplImage *src = cvLoadImage("e://five.jpg", CV_LOAD_IMAGE_GRAYSCALE);
IplImage *dsc = cvCreateImage(cvSize(src->width*0.5,src->height*0.5), src->depth, src->nChannels);
// 转换图像大小
cvResize(src, dsc, CV_INTER_LINEAR);
src->width*=0.5;
src->height*=0.5;
// 复制图像
// 两个图像的大小类型通道数必须相同
cvCopy(dsc, src );
cvNamedWindow("src", CV_WINDOW_AUTOSIZE);
cvShowImage("src", src);
// 取图像阀值
unsigned int threshold = Otsu((unsigned char *)src->imageData, src->width, src->height, src->widthStep);
// 图像二值化
if (TRUE == Threshold((unsigned char *)src->imageData, src->width, src->height, src->widthStep,
threshold))
{
cvNamedWindow("dsc", CV_WINDOW_AUTOSIZE);
cvShowImage("dsc", src);
// 图像取反
// cvNot(src, src);
FindContours((unsigned char *)src->imageData,src->width , src->height, src->widthStep);
cvNamedWindow("not", CV_WINDOW_AUTOSIZE);
cvShowImage("not", src);
cvWaitKey(0);
}
cvDestroyAllWindows();
cvReleaseImage(&src);
cvReleaseImage(&dsc);
printf("Hello World!/n");
return 0;
}
#include <cv.h>
#include <highgui.h>
#include <windows.h>
// 获取直方图
// 1. pImageData 图像数据
// 2. nWidth 图像宽度
// 3. nHeight 图像高度
// 4. nWidthStep 图像行大小
// 5. pHistogram 直方图
BOOL GetHistogram(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep,
int *pHistogram)
{
int i = 0;
int j = 0;
unsigned char *pLine = NULL;
// 清空直方图
memset(pHistogram, 0, sizeof(int) * 256);
for (pLine = pImageData, j = 0; j < nHeight; j++, pLine += nWidthStep)
{
for (i = 0; i < nWidth; i++)
{
pHistogram[pLine[i]]++;
}
}
return TRUE;
}
// 大津法取阈值
// 1. pImageData 图像数据
// 2. nWidth 图像宽度
// 3. nHeight 图像高度
// 4. nWidthStep 图像行大小
// 函数返回阈值
int Otsu(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep)
{
int i = 0;
int j = 0;
int nTotal = 0;
int nSum = 0;
int A = 0;
int B = 0;
double u = 0;
double v = 0;
double dVariance = 0;
double dMaximum = 0;
int nThreshold = 0;
int nHistogram[256];
// 获取直方图
GetHistogram(pImageData, nWidth, nHeight, nWidthStep, nHistogram);
for (i = 0; i < 256; i++)
{
nTotal += nHistogram[i];
nSum += (nHistogram[i] * i);
}
for (j = 0; j < 256; j++)
{
A = 0;
B = 0;
for (i = 0; i < j; i++)
{
A += nHistogram[i];
B += (nHistogram[i] * i);
}
if (A > 0)
{
u = B / A;
}
else
{
u = 0;
}
if (nTotal - A > 0)
{
v = (nSum - B) / (nTotal - A);
}
else
{
v = 0;
}
dVariance = A * (nTotal - A) * (u - v) * (u - v);
if (dVariance > dMaximum)
{
dMaximum = dVariance;
nThreshold = j;
}
}
return nThreshold;
}
// 二值化
// 1. pImageData 图像数据
// 2. nWidth 图像宽度
// 3. nHeight 图像高度
// 4. nWidthStep 图像行大小
// 5. nThreshold 阈值
BOOL Threshold(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep,
unsigned int nThreshold)
{
int i = 0;
int j = 0;
unsigned char *pLine = NULL;
for (pLine = pImageData, j = 0; j < nHeight; j++, pLine += nWidthStep)
{
for (i = 0; i < nWidth; i++)
{
if (pLine[i] >= nThreshold)
{
pLine[i] = 0x00;
}
else
{
pLine[i] = 0xff;
}
}
}
return TRUE;
}
// 二值化图像取反
void Not(IplImage *edge)
{
int i;
int j;
for(i=0;i<edge->height;i++)
for(j=0;j<edge->width;j++)
{
if(edge->imageData[edge->height*i+j]==0)
edge->imageData[edge->height*i+j]=1;
else
edge->imageData[edge->height*i+j]=0;
}
}
BOOL FindContours(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep)
{
int i = 0;
int j = 0;
unsigned char *pLine[3] = { NULL, NULL, NULL };
for (j = 1; j < nHeight - 1; j++)
{
pLine[0] = pImageData + nWidthStep * (j - 1);
pLine[1] = pImageData + nWidthStep * j;
pLine[2] = pImageData + nWidthStep * (j + 1);
for (i = 1; i < nWidth - 1; i++)
{
if (pLine[0][i-1] == 0xFF && pLine[0][i] == 0xFF && pLine[0][i+1] == 0xFF &&
pLine[1][i-1] == 0xFF && pLine[1][i] == 0xFF && pLine[1][i+1] == 0xFF &&
pLine[2][i-1] == 0xFF && pLine[2][i] == 0xFF && pLine[2][i+1] == 0xFF)
{
pLine[0][i-1] = 0;
}
else
{
pLine[0][i-1] = pLine[1][i];
}
}
}
return TRUE;
}
int main(int argc, char* argv[])
{
IplImage *src = cvLoadImage("e://five.jpg", CV_LOAD_IMAGE_GRAYSCALE);
IplImage *dsc = cvCreateImage(cvSize(src->width*0.5,src->height*0.5), src->depth, src->nChannels);
// 转换图像大小
cvResize(src, dsc, CV_INTER_LINEAR);
src->width*=0.5;
src->height*=0.5;
// 复制图像
// 两个图像的大小类型通道数必须相同
cvCopy(dsc, src );
cvNamedWindow("src", CV_WINDOW_AUTOSIZE);
cvShowImage("src", src);
// 取图像阀值
unsigned int threshold = Otsu((unsigned char *)src->imageData, src->width, src->height, src->widthStep);
// 图像二值化
if (TRUE == Threshold((unsigned char *)src->imageData, src->width, src->height, src->widthStep,
threshold))
{
cvNamedWindow("dsc", CV_WINDOW_AUTOSIZE);
cvShowImage("dsc", src);
// 图像取反
// cvNot(src, src);
FindContours((unsigned char *)src->imageData,src->width , src->height, src->widthStep);
cvNamedWindow("not", CV_WINDOW_AUTOSIZE);
cvShowImage("not", src);
cvWaitKey(0);
}
cvDestroyAllWindows();
cvReleaseImage(&src);
cvReleaseImage(&dsc);
printf("Hello World!/n");
return 0;
}
相关文章推荐
- opencv-图像二值化、阈值获取、直方图、轮廓提取(转)
- opencv-图像二值化、阈值获取、直方图、轮廓提取(转)
- 使用Opencv进行轮廓检测,字符提取,简单的直方图字符识别!
- OpenCV提取轮廓的方法获取瞳孔区域及中心
- opencv 提取轮廓大于某个阈值的图像
- Dlib+opencv实时提取人脸轮廓(windows环境下//Dlib配置入门)
- OpenCV成长之路:直线、轮廓的提取与描述
- 已知图片某区域内所有点坐标,求区域周长(非opencv轮廓提取)
- opencv轮廓提取
- opencv学习_9 (轮廓提取)
- Opencv之获取边缘和画轮廓
- opencv色彩空间转换,提取单通道,直方图等示例
- matlab使用opencv (轮廓提取+直线拟合)
- OpenCV下设置灰度直方图的阈值来对图像进行查找(查表)变换的源码
- opencv获取灰度图像直方图
- OpenCV示例学习笔记(1)-contours2.cpp-通过findContours 函数实现轮廓提取
- OpenCV_基于局部自适应阈值的图像二值化
- opencv学习:提取物体的轮廓矩
- OpenCV成长之路:直线、轮廓的提取与描述
- OpenCV学习——图像轮廓的提取和绘制