【图像算法】彩色图像分割专题六:一种基于颜色直方图的图像分割

时间:2022-12-09 15:31:11

【图像算法】彩色图像分割专题六:一种基于颜色直方图的图像分割

     SkySeraph Jun 14th 2011  HQU

Email:zgzhaobo@gmail.com    QQ:452728574

Latest Modified Date:Jun 14th 2011 HQU

一 原理及说明:

1   首先RGB转HSV,在HSV空间下,对颜色分量H和S分别通过直方图,手动取范围进行分割。 关于RGB转HSV参考:http://www.cnblogs.com/skyseraph/archive/2011/05/05/2038317.html

2   关于颜色直方图相关资料:

http://www.opencv.org.cn/index.php/%E5%9B%BE%E5%83%8F%E9%A2%9C%E8%89%B2%E5%88%86%E5%B8%83%E7%9B%B4%E6%96%B9%E5%9B%BE

http://blog.csdn.net/foolpanda1168/archive/2010/12/15/6078463.aspx

http://www.cnblogs.com/xrwang/archive/2010/02/04/howtousehistogram.html

http://blog.csdn.net/yanqingan/archive/2010/06/14/5670951.aspx

 二 核心源码:

①响应函数

/////////////////////////////////////////////////////////////////////////////
void CColorSegDlg::OnHistDlgSeg()
//直方图分割(H/S分量)
{
// 验证
if(!(ToDisplayCtr1))
{
MessageBox("Please Load Pic!");
return;
}

// 定义工作位图
IplImage* src;
src = ToDisplayCtr1;

IplImage* imgH = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* imgS = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);

// 源图像信息
int width = src->width;
int height = src->height;
int channel = src->nChannels;

// 色彩空间转化
int i,j;
double R,G,B,H,S,V;
for(j=0;j<height;j++)
{
for(i=0;i<width;i++)
{
B = ((uchar*)(src->imageData + j*src->widthStep))[i*channel];
G = ((uchar*)(src->imageData + j*src->widthStep))[i*channel+1];
R = ((uchar*)(src->imageData + j*src->widthStep))[i*channel+2];
pMyColorSpace.RGB2HSV(R,G,B,H,S,V);
H = (360*H)/(2*PI); // 弧度制[0,2pi]转换为角度[0,360]
H = (250*H)/(360); //[0,250] -- [0,360]
S = S*255;
((uchar*)(imgH->imageData + j*imgH->widthStep))[i*imgH->nChannels] = (uchar)H;
((uchar*)(imgS->imageData + j*imgS->widthStep))[i*imgS->nChannels] = (uchar)S;
}
}

// 处理
pMyThreshold.HistDlgSegment(imgH);
pMyThreshold.HistDlgSegment(imgS);

cvReleaseImage(&imgH);
cvReleaseImage(&imgS);

}

②函数模块

/////////////////////////////////////////////////////////////////////////////////
// **直方图分割**
// 06/10/2011
// Copyright: @skyseraph zgzhaobo@gmail.com
// Version: 6/10/2011 zhaobo
/////////////////////////////////////////////////////////////////////////////////
void MyThreshold::HistDlgSegment(IplImage* img)
{
if(img->nChannels != 1)
{
AfxMessageBox("It's not a SigleChannelPic!");
return;
}

//=====================输入图像信息====================//
int imgWidth = img->width;
int imgHeight = img->height;
int imgDepth = img->depth;
int imgChannels = img->nChannels;
int imgSize = img->imageSize;
int imgStep = img->widthStep/sizeof(uchar);
uchar* imgData = (uchar *)img->imageData;
int imgLen = imgWidth*imgHeight;

//保存像素范围
int m_lowerLimit,m_upperLimit;

//指向灰度级的数据指针
int *pArray;
//分配内存
pArray = new int[256];
//初始化内存
for(int i =0 ;i <256 ;i++)
{
pArray[i] = 0;
}

//总的象素个数
int Total;
Total = imgWidth * imgHeight ;

//调用函数获得每一级灰度级的值
HuiDuTongJi(img,pArray);

//
HistDlg m_dlg;
m_dlg.pArray = pArray;
m_dlg.m_total = Total;


if(m_dlg.DoModal() == IDOK)
{
//获得分割的上限和下限
if(m_dlg.m_lowerLimit > m_dlg.m_upperLimit)
{
m_lowerLimit = m_dlg.m_upperLimit;
m_upperLimit = m_dlg.m_lowerLimit;
}
else
{
m_lowerLimit = m_dlg.m_lowerLimit;
m_upperLimit = m_dlg.m_upperLimit;
}
//阈值分割
HistThreshold(img,m_lowerLimit,m_upperLimit);
}

delete[]m_dlg;
delete []pArray;
}


/////////////////////////////////////////////////////////////////////////////////
void MyThreshold::HuiDuTongJi(IplImage* img,int *pArray)
//图像的灰度统计
{
if(img->nChannels != 1)
{
AfxMessageBox("It's not a SigleChannelPic!");
return;
}

//=====================循环变量====================//
int i,j;
//=====================输入图像信息====================//
int imgWidth = img->width;
int imgHeight = img->height;
int imgDepth = img->depth;
int imgChannels = img->nChannels;
int imgSize = img->imageSize;
int imgStep = img->widthStep/sizeof(uchar);
uchar* imgData = (uchar *)img->imageData;
int imgLen = imgWidth*imgHeight; //

//统计灰度级
for(i = 0 ; i< imgHeight ; i++)
{
for(j = 0; j< imgWidth ; j++)
{
pArray[imgData[i*imgStep+j*imgChannels]]++;
}
}
}
/////////////////////////////////////////////////////////////////////////////////
//参数:
// m_lowerLimit //阈值下限
// m_upperLimit //阈值上限
/////////////////////////////////////////////////////////////////////////////////
void MyThreshold::HistThreshold(IplImage* img, int m_lowerLimit, int m_upperLimit)
//灰度直方图阈值分割
{
//=====================循环变量====================//
int i,j,k;
//=====================输入图像信息====================//
int imgWidth = img->width;
int imgHeight = img->height;
int imgDepth = img->depth;
int imgChannels = img->nChannels;
int imgSize = img->imageSize;
int imgStep = img->widthStep/sizeof(uchar);
uchar* imgData = (uchar *)img->imageData;
int imgLen = imgWidth*imgHeight; // //

IplImage* dst = cvCreateImage(cvGetSize(img),img->depth,img->nChannels);

for(i = 0 ;i < imgHeight; i++)
{
for(j =0 ; j <imgWidth ; j++)
{
for(k = 0; k<imgChannels;k++)
{
//当灰度值不在范围之内时灰度值付为0,否则为255
if( imgData[i*imgStep+j*imgChannels+k] <m_lowerLimit || imgData[i*imgStep+j*imgChannels+k] > m_upperLimit)
{
(((uchar *)(dst->imageData))[i*imgStep+j*imgChannels+k]) = 255;
}
else
{
(((uchar *)(dst->imageData))[i*imgStep+j*imgChannels+k]) = 0;

}
}
}
}

cvNamedWindow("src");
cvShowImage("src",img);
cvNamedWindow("dst");
cvShowImage("dst",dst);


cvSaveImage(".\\dst.jpg",dst);
cvSaveImage(".\\src.jpg",img);

cvWaitKey(0);
cvDestroyAllWindows();
cvReleaseImage(&dst);
}
/////////////////////////////////////////////////////////////////////////////////

三 效果:

①H下:

原图及H直方图:

【图像算法】彩色图像分割专题六:一种基于颜色直方图的图像分割

H单通道图像:

【图像算法】彩色图像分割专题六:一种基于颜色直方图的图像分割

H直方图分割结果:

【图像算法】彩色图像分割专题六:一种基于颜色直方图的图像分割

②S下

原图及S直方图:

【图像算法】彩色图像分割专题六:一种基于颜色直方图的图像分割

S单通道图像:

【图像算法】彩色图像分割专题六:一种基于颜色直方图的图像分割

S直方图分割结果:

【图像算法】彩色图像分割专题六:一种基于颜色直方图的图像分割

 

More in  http://skyseraph.com/2011/08/27/CV/图像算法专题/ 

 

-------------------------------------------------------------------------------------------------------------------------------

Author:         SKySeraph

Email/GTalk: zgzhaobo@gmail.com    QQ:452728574

From:         http://www.cnblogs.com/skyseraph/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

 -------------------------------------------------------------------------------------------------------------------------------