主要對每個色塊顏色平均值提取後存儲到文件,用彩色閾值分割的方法先進行逐個色塊的分割,再進行平均值提取,本算法還可以優化,算法時間還可縮短。
主要代碼如下:
void HuiDuTongJi(IplImage* img,int *pArray)
//圖像的灰度統計
{
if(img->nChannels != 1)
{
cout<<"It's not a SigleChannelPic!"<<endl;
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]]++;
}
}
}
void HistThreshold(IplImage* img, double m_lowerLimit, double 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;
}
}
}
}
cvCopy(dst,img,0);
cvReleaseImage(&dst);
}
/*直方圖方法分割彩色圖像 */
void HistSegment(IplImage* img,double lowerLimit, double upperLimit)
{
if(img->nChannels != 1)
{
cout<<"It's not a SigleChannelPic!"<<endl;
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;
//保存像素範圍
double 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);
m_lowerLimit = lowerLimit;
m_upperLimit = upperLimit;
//閾值分割
HistThreshold(img,m_lowerLimit,m_upperLimit);
delete []pArray;
}
int picSegProcess::seKaSegment(IplImage *pSrcImage,CvScalar lowerLimit, CvScalar upperLimit, CvScalar *resultColor,CvRect *rectParam)
{
// 定義工作位圖
IplImage* src=pSrcImage;
IplImage* imgR = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* imgG = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* imgB = cvCreateImage(cvGetSize(src),IPL_DEPTH_8U,1);
IplImage* imgResult = 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;
int sumR=0,sumG=0,sumB=0;
int RGBnum=0;
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];
((uchar*)(imgR->imageData + j*imgR->widthStep))[i*imgR->nChannels] = (uchar)R;
((uchar*)(imgG->imageData + j*imgG->widthStep))[i*imgG->nChannels] = (uchar)G;
((uchar*)(imgB->imageData + j*imgB->widthStep))[i*imgB->nChannels] = (uchar)B;
}
}
static void testSekaSeg()
{
IplImage *pRoiImage =NULL;
IplImage *tempResult =NULL;
char pic_path[MAX_PATH]={0};
char tempS[MAX_PATH]={0};
char buf[256]={0};
picSegProcess mytest;
GetCurrentDirectory(MAX_PATH,pic_path);
sprintf(tempS, "%s%s", pic_path,"\\pic\\mytest1.jpg");
pRoiImage = cvLoadImage(tempS, CV_LOAD_IMAGE_UNCHANGED);
int rectW = 6;//橫向色塊數
int rectH = 4;//縱向色塊數
int segParam=5;//RGB顏色判斷範圍
int tempHeigh=pRoiImage->height/rectH;
int tempWidth=pRoiImage->width/rectW;
int HRemainder=pRoiImage->height%rectH;
int WRemainder=pRoiImage->width%rectW;
int h=0;
int w=0;
int tempNum=0;
CvScalar tempColor;
CvScalar avrColor;
CvRect rectParam;
FILE* tempFd=NULL;
IplImage *tempDest= cvCreateImage(cvGetSize(pRoiImage), pRoiImage->depth, pRoiImage->nChannels);
sprintf(tempS, "%s%s", pic_path,"\\avrResult.txt");
for (h=0;h<pRoiImage->height-HRemainder;h+=tempHeigh)
{
for (w=0;w<pRoiImage->width-WRemainder;w+=tempWidth)
{
/*CvPoint pt1;
pt1.x=w;
pt1.y=h;
CvPoint pt2;
pt2.x=w+tempWidth;
pt2.y=h+tempHeigh;
cvRectangle(pRoiImage,pt1,pt2,Scalar(0,255,0));*/
cvCopy(pRoiImage,tempDest,0);
tempColor.val[0] = ((uchar*)(tempDest->imageData + (h+tempHeigh/2)*tempDest->widthStep))[(w+tempWidth/2)*tempDest->nChannels];
tempColor.val[1] = ((uchar*)(tempDest->imageData + (h+tempHeigh/2)*tempDest->widthStep))[(w+tempWidth/2)*tempDest->nChannels+1];
tempColor.val[2] = ((uchar*)(tempDest->imageData + (h+tempHeigh/2)*tempDest->widthStep))[(w+tempWidth/2)*tempDest->nChannels+2];
CvScalar LColor = cvScalar(tempColor.val[0]-segParam,tempColor.val[1]-segParam,tempColor.val[2]-segParam);
CvScalar UpColor = cvScalar(tempColor.val[0]+segParam,tempColor.val[1]+segParam,tempColor.val[2]+segParam);
rectParam.x=w;
rectParam.y=h;
rectParam.height=tempHeigh;
rectParam.width=tempWidth;
mytest.seKaSegment(tempDest,LColor,UpColor,&avrColor,&rectParam);
tempNum++;
if((tempFd = fopen(tempS,"a+"))==NULL){
if(NULL != tempS)
printf("can not open file %s\n",tempS);
else
printf("can not open file,file path is NULL\n");
return;
}
sprintf(buf,"%d,B:%f,G:%f,R:%f\n",tempNum, avrColor.val[0],avrColor.val[1],avrColor.val[2]);
fwrite(buf,strlen(buf)+1,1,tempFd);
fclose(tempFd);
}
}
/*sprintf(tempS, "%s%s", pic_path,"\\picResult\\testSekaSeg.jpg");
cvSaveImage( tempS, pRoiImage,0);*/
cvReleaseImage(&tempDest);
cvReleaseImage(&pRoiImage);
}
原圖像
色塊分割實例圖像