根据项目需求,需要将c++代码改成c语言,最后移植到DSP上。这里记录了opencv中的高斯滤波、大津阈值、直方图均衡、膨胀、Sobel算法、霍夫变换求截距六个函数改成c语言的算法。在此记录下。
//opencv函数改写c
void Kernel(int size,float sigma);
void GaussianFilter (const unsigned char* pGauBlurSource);
void OtsuThreshold(const unsigned char* pOtsuSource);
void HisEqualization(const unsigned char* pHistEqualSource);
void Dilation(const unsigned char* pDilationSource);
void Sobel(const unsigned char* pSobelSource);
int HoughLines(const unsigned char* pHoughLinesSource);
void KernelSignal(int size,float sigma);
void ImprovedGaussianFilter (unsigned char* pImprovedGauBlurSource);
void ImprovedDilation(const unsigned char *pDilationSource);
void ImprovedSobel(unsigned char* pSobelSource);
//循环遍历计数
int i;
int j;
int m;
int n;
//高斯滤波的模板,由高斯函数生成
float CoefArray[9]={0.106997,0.113110,0.106997,0.113110,0.119572,0.113110,0.106997,0.113110,0.106997};
//高斯滤波的模板,由高斯函数生成
const float ImprovedCoefArray[3]={0.327104,0.345791,0.327104};
const int GrayScale = 256;
int wSize = 1500;
int hSize = 180;
const int pixelSum = 270000;
const float PI = 3.141596;
//高斯滤波用到的局部变量
unsigned char* pGauBlurResult;
int CoefArray_index = 0;
unsigned char sum = 0;
//大津阈值用到的局部变量
int pixelCount[256];
float pixelPro[256];
int threshold;
float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaMax ;
float deltatmp;
unsigned char* pOtsuSourceTmp;
unsigned char* pOtsuResult;
//直方图均衡用到的局部变量
unsigned char* ptr;
unsigned int tmp_hist[256];
unsigned int map[256]; //灰度映射表
int histogram[256];//图像像素值个数统计
int *pHistogram; //指针定义
unsigned char* pHistEqualSourceTmp;
unsigned char* pHistResult;
//膨胀用到的局部变量
unsigned char* pDilationResult;
int flag;
//Sobel用到的局部变量
unsigned char* pSobelResult;
unsigned char amplitudeTmp;
unsigned char gradX;
unsigned char gradY;
//改进版的Sobel
unsigned char* pSobelSourceTmp;
float threshold = 0.6*255;
int pix;
//霍夫变换求截距用到的局部变量
const int theta = 180;
//const int diagonalDistance = 1510;//对角线长度
int distance;
int diagonal;
int tmpDiatance;
int tmpX;
int tmpY;
int intercept;
int** linesCount;
int** linesY;
//----------高斯滤波----------//
void GaussianFilter (const unsigned char* pGauBlurSource)
{
//边缘不做处理
for(i=0;i<wSize;i++)
pGauBlurResult[i] = pGauBlurSource[i];
for(i=(hSize-1)*wSize;i<pixelSum;i++)
pGauBlurResult[i] = pGauBlurSource[i];
for(i=wSize;i<(hSize-2)*wSize+1;i+=wSize)
pGauBlurResult[i] = pGauBlurSource[i];
for(i=wSize*2-1;i<(hSize-1)*wSize;i+=wSize)
pGauBlurResult[i] = pGauBlurSource[i];
for (i=1;i<hSize-1;i++) //边缘不处理
{
for (j=1;j<wSize-1;j++)
{
sum = 0;
CoefArray_index = 0;
for ( m=i-1; m<i+2; m++)
{
for (n=j-1; n<j+2; n++)
{
sum += pGauBlurSource [ m*wSize + n] * CoefArray[CoefArray_index] ;
CoefArray_index++;
}
}
if (sum > 255)
sum = 255;
pGauBlurResult[i*wSize+j] = sum;
}
}
}
//------------改进版高斯滤波------------//
void ImprovedGaussianFilter (unsigned char* pImprovedGauBlurSource)
{
//边缘不做处理
for(i=0;i<wSize;i++)
pGauBlurResult[i] = pImprovedGauBlurSource[i];
for(i=(hSize-1)*wSize;i<pixelSum;i++)
pGauBlurResult[i] = pImprovedGauBlurSource[i];
for(i=wSize;i<(hSize-2)*wSize+1;i+=wSize)
pGauBlurResult[i] = pImprovedGauBlurSource[i];
for(i=wSize<<1-1;i<(hSize-1)*wSize;i+=wSize)
pGauBlurResult[i] = pImprovedGauBlurSource[i];
for (i=1;i<hSize-1;i++)
{
for (j=1;j<wSize-1;j++)
{
sum = pImprovedGauBlurSource[i*wSize+j-1]*ImprovedCoefArray[0]+pImprovedGauBlurSource[i*wSize+j]*ImprovedCoefArray[1]+pImprovedGauBlurSource[i*wSize+j+1]*ImprovedCoefArray[2];
if (sum > 255)
sum = 255;
pGauBlurResult[i*wSize+j] = sum;
}
}
for (j=1;j<wSize-1;j++)
{
for (i=1;i<hSize-1;i++)
{
sum = pGauBlurResult[(i-1)*wSize+j]*ImprovedCoefArray[0]+pGauBlurResult[i*wSize+j]*ImprovedCoefArray[1]+pGauBlurResult[(i+1)*wSize+j]*ImprovedCoefArray[2];
if (sum > 255)
sum = 255;
pGauBlurResult[i*wSize+j] = sum;
}
}
}
//-----------大津阈值------------//
void OtsuThreshold(const unsigned char* pOtsuSource)
{
//printf("come into OtsuThreshold\n");
deltaMax = 0;
threshold = 0;
pOtsuSourceTmp = pOtsuSource;
for (i = 0; i < GrayScale; i++)
{
pixelCount[i] = 0;
pixelPro[i] = 0.0;
}
//统计灰度级中每个像素在整幅图像中的个数
for(i = 0;i < pixelSum;i++)
{
pixelCount[(int)(*pOtsuSourceTmp)] ++; //将像素值作为计数数组的下标
pOtsuSourceTmp++;
}
//计算每个像素在整幅图像中的比例
for (i = 0; i < GrayScale; i++)
pixelPro[i] = (float)pixelCount[i] / pixelSum;
//w0为背景像素点占整幅图像的比例;u0tmp为背景像素点的平均灰度值;w1为前景像素点占整幅图像的比例;u1tmp为前景像素点的平均灰度值;u为整幅图像的平均灰度
//遍历灰度级[0,255]
for (i = 0; i < GrayScale; i++) // i作为阈值
{
w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = 0.0;
deltatmp = 0.0;
for (j = 0; j < GrayScale; j++)
{
if (j <= i) //背景部分
{
w0 += pixelPro[j];
u0tmp += j * pixelPro[j];
}
else //前景部分
{
w1 += pixelPro[j];
u1tmp += j * pixelPro[j];
}
}
u0 = u0tmp/w0;
u1 = u1tmp/w1;
u = u0tmp + u1tmp;
deltatmp = w0*w1*(u0-u1)*(u0-u1);//w0 * (u0 - u) * (u0 - u) + w1 * (u1 - u) * (u0 - u);
if (deltatmp > deltaMax)
{
deltaMax = deltatmp;
threshold = i;
}
}
//printf("threshold=%d\n",threshold);
//根据阈值threshold进行分割
pOtsuSourceTmp = pOtsuSource;
for(i = 0;i<pixelSum;i++)
{
if((int)*pOtsuSourceTmp > threshold)
*pOtsuResult = 255;
else
*pOtsuResult = 0;
pOtsuSourceTmp++;
pOtsuResult++;
}
pOtsuResult = &Pixel_Otsu[0];
}
//--------------直方图均衡--------------//
void HisEqualization(const unsigned char *pHistEqualSource)
{
pHistEqualSourceTmp = pHistEqualSource;
pHistogram = histogram;
for(i=0;i<256;i++)
histogram[i]=0;
//统计各个灰度值的个数
pHistEqualSourceTmp=pHistEqualSource;
for(i=0;i<pixelSum;i++)//遍历图像中的所有像素
{
pHistogram=histogram; //指针指向直方图数组
pHistogram = pHistogram + *pHistEqualSourceTmp;//取当前像素的灰度值作为直方图数组的偏移量
*pHistogram=*pHistogram +1;//对应偏移量的直方图数组元素值累加1
pHistogram=histogram;//指针重指向直方图数组的起始地址
pHistEqualSourceTmp++;//图像指针指向下一个像素地址
}
//初始化直方图数组
for(i=0;i<256;i++)
tmp_hist[i] = histogram[i];
//直方图均衡
for(i=1; i<256; i++)
tmp_hist[i] += tmp_hist[i-1];//计算原始图像的累计直方图
//建立映射表
for(i=0; i<256; i++)
map[i] = tmp_hist[i]*255/pixelSum;
//给图片赋予新值
pHistEqualSourceTmp=pHistEqualSource;
for(i = 0 ; i < pixelSum;i++)
{
ptr=pHistEqualSourceTmp++;
*pHistResult=map[*ptr];
pHistResult++;
}
pHistResult = &Pixel_Hist[0];
}
//------------膨胀------------//
void Dilation(const unsigned char *pDilationSource)
{
printf("come into dilation\n");
//边缘不做处理
for(i=0;i<wSize;i++)
pDilationResult[i] = pDilationSource[i];
for(i=(hSize-1)*wSize;i<pixelSum;i++)
pDilationResult[i] = pDilationSource[i];
for(i=wSize;i<(hSize-2)*wSize+1;i+=wSize)
pDilationResult[i] = pDilationSource[i];
for(i=wSize*2-1;i<(hSize-1)*wSize;i+=wSize)
pDilationResult[i] = pDilationSource[i];
for(i = 1;i < hSize - 1;i++)
{
for(j = 1;j < wSize - 1;j++)
{
flag = 1;
for(int m = i - 1;m < i + 2;m++)
{
for(int n = j - 1; n < j + 2;n++)
{
//自身及领域中若有一个为255
//则将该点设为255
if((int)pDilationSource[i * wSize + j] == 255|| (int)pDilationSource[m * wSize + n] == 255)
{
flag = 0;
break;
}
}
if(flag == 0)
break;
}
if(flag == 0)
pDilationResult[i * wSize + j] = 255;
else
pDilationResult[i * wSize + j] = 0;
}
}
}
//------------改进版的膨胀------------//
void ImprovedDilation(const unsigned char *pDilationSource)
{
//printf("come into dilation\n");
//边缘不做处理
for(i=0;i<wSize;i++)
pDilationResult[i] = pDilationSource[i];
for(i=(hSize-1)*wSize;i<pixelSum;i++)
pDilationResult[i] = pDilationSource[i];
for(i=wSize;i<(hSize-2)*wSize+1;i+=wSize)
pDilationResult[i] = pDilationSource[i];
for(i=wSize*2-1;i<(hSize-1)*wSize;i+=wSize)
pDilationResult[i] = pDilationSource[i];
for(i = 1;i < hSize - 1;i++)
{
for(j = 1;j < wSize - 1;j++)
{
//自身及领域中若有一个为255
//则将该点设为255
if((int)pDilationSource[i * wSize + j-1] == 255 || (int)pDilationSource[i * wSize + j] == 255||(int)pDilationSource[i * wSize + j+1] == 255)
pDilationResult[i * wSize + j] = 255;
else
pDilationResult[i * wSize + j] = 0;
}
}
for(j = 1;j < wSize - 1;j++)
{
for(i = 1;i < hSize - 1;i++)
{
//自身及领域中若有一个为255
//则将该点设为255
if((int)pDilationSource[(i-1) * wSize + j] == 255 || (int)pDilationSource[i * wSize + j] == 255||(int)pDilationSource[(i+1) * wSize + j] == 255)
pDilationResult[i * wSize + j] = 255;
else
pDilationResult[i * wSize + j] = 0;
}
}
}
//------------------霍夫变换---------------//
int HoughLines(const unsigned char *pHoughLinesSource)
{
//printf("come into HoughLines\n");
distance = 0;
diagonal = (int)sqrt(pow(hSize,2)+pow(wSize,2));
linesCount = (int**)malloc(theta*sizeof(int*));
linesY = (int**)malloc(theta*sizeof(int*));
for(i=0;i<theta;i++)
{
linesCount[i] = (int*)malloc(diagonal*sizeof(int));
linesY[i] = (int*)malloc(diagonal*sizeof(int));
}
for(i=0;i<theta;i++)
{
for(j=0;j<diagonal;j++)
{
linesCount[i][j] = 1;
linesY[i][j] = 1;
}
}
for(i=0;i<hSize;i++)
{
for(j=0;j<wSize;j++)
{
if((int)pHoughLinesSource[i*wSize+j]!=0)
{
for(m=1;m<theta;m++)
{
distance = (int)(i*cos(PI*m/180)+j*sin(PI*m/180));
distance = (int)(distance/2+diagonal/2);//对distance值优化,防止为负
linesCount[m][distance] +=1;
linesY[m][distance] += i;
}
}
}
}
tmpDiatance = linesCount[0][0];
tmpX = 0;
tmpY = 0;
for(i=0;i<theta;i++)
{
for(j=0;j<diagonal;j++)
{
if(linesCount[i][j]>tmpDiatance)
{
tmpDiatance = linesCount[i][j];
tmpX = i;
tmpY = j;
}
}
}
intercept = linesY[tmpX][tmpY]/linesCount[tmpX][tmpY];
printf("intercept = %d\n",intercept);
return intercept;
}
//-------------Sobel算法----------//
void Sobel(const unsigned char *pSobelSource)
{
//printf("come into Sobel\n");
//边缘不做处理
for(i=0;i<wSize;i++)
pSobelResult[i] = 0;
for(i=(hSize-1)*wSize;i<pixelSum;i++)
pSobelResult[i] = 0;
for(i=wSize;i<(hSize-2)*wSize+1;i+=wSize)
pSobelResult[i] = 0;
for(i=wSize*2-1;i<(hSize-1)*wSize;i+=wSize)
pSobelResult[i] = 0;
for(int i=1;i<(hSize-1);i++)
{
for(int j=1;j<(wSize-1);j++)
{
//通过指针遍历图像上每一个像素
gradX=pSobelSource[(i-1)*wSize+j+1]+pSobelSource[i*wSize+j+1]*2+pSobelSource[(i+1)*wSize+j+1]-pSobelSource[(i-1)*wSize+j-1]-pSobelSource[i*wSize+j-1]*2-pSobelSource[(i+1)*wSize+j-1];
gradY=pSobelSource[(i+1)*wSize+j-1]+pSobelSource[(i+1)*wSize+j]*2+pSobelSource[(i+1)*wSize+j+1]-pSobelSource[(i-1)*wSize+j-1]-pSobelSource[(i-1)*wSize+j]*2-pSobelSource[(i-1)*wSize+j+1];
amplitudeTmp = abs(gradX)+abs(gradY);
if(amplitudeTmp>255)
amplitudeTmp = 255;
pSobelResult[i*wSize+j] = amplitudeTmp;
}
}
}
//-------------改进版Sobel算法----------//
void ImprovedSobel(unsigned char* pSobelSource)
{
//printf("come into ImprovedSobel\n");
pSobelSourceTmp = pSobelSource;
//边缘不做处理
for(i=0;i<wSize;i++)
pSobelResult[i] = 0;
for(i=(hSize-1)*wSize;i<pixelSum;i++)
pSobelResult[i] = 0;
for(i=wSize;i<(hSize-2)*wSize+1;i+=wSize)
pSobelResult[i] = 0;
for(i=wSize<<1-1;i<(hSize-1)*wSize;i+=wSize)
pSobelResult[i] = 0;
for(i=1+wSize;i<(hSize-1)*wSize-1;i++)
{
gradX = 0;//水平
gradY = 0;//垂直
gradX+=(*(pSobelSourceTmp+i-1-wSize))+(*(pSobelSourceTmp+i-wSize))<<1+(*(pSobelSourceTmp+i+1-wSize))-(*(pSobelSourceTmp+i-1+wSize))-(*(pSobelSourceTmp+i+wSize))<<1-(*(pSobelSourceTmp+i+1+wSize));
gradY+=(*(pSobelSourceTmp+i-1-wSize))+(*(pSobelSourceTmp+i-1))<<1+(*(pSobelSourceTmp+i-1+wSize))-(*(pSobelSourceTmp+i+1-wSize))-(*(pSobelSourceTmp+i+1))<<1-(*(pSobelSourceTmp+i+1+wSize));
gradX = abs(gradX);
gradY = abs(gradY);
pix = gradY>gradX?gradY:gradX;
*(pSobelResult+i)= pix>threshold?255:0;
}
}
//--------------计算高斯核系数-------------//
void Kernel(int size,float sigma)
{
//计算sigmaX的值
float sigmaX;
float sum = 0;
float gaus[3][3];
const float PI=4.0*atan(1.0); //圆周率π赋值
int center=size/2;
int k =0;
if(sigma>0)
sigmaX = sigma;
else
sigmaX = ((size-1)*0.5 - 1)*0.3 +0.8;
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
gaus[i][j]=(1/(2*PI*sigmaX*sigmaX))*exp(-((i-center)*(i-center)+(j-center)*(j-center))/(2*sigmaX*sigmaX));
sum+=gaus[i][j];
}
}
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
gaus[i][j]/=sum;
CoefArray[k] = gaus[i][j];
printf(" %f",CoefArray[k]);
k++;
}
printf("\n");
}
}
//------------计算改进版的高斯核系数---------------//
void KernelSignal(int size,float sigma)
{
//计算sigmaX的值
float sigmaX;
float sum = 0;
float gaus[3];
const float PI=4.0*atan(1.0); //圆周率π赋值
int center=size/2;
int k =0;
if(sigma>0)
sigmaX = sigma;
else
sigmaX = ((size-1)*0.5 - 1)*0.3 +0.8;
for(i=0;i<size;i++)
{
gaus[i]=(1/(2*PI*sigmaX*sigmaX))*exp(-((i-center)*(i-center))/(2*sigmaX*sigmaX));
sum+=gaus[i];
}
for(i=0;i<size;i++)
{
gaus[i]/=sum;
CoefArray[k] = gaus[i];
printf(" %f",CoefArray[k]);
k++;
printf("\n");
}
}