某些opencv函式改成c語言實現
阿新 • • 發佈:2018-12-19
根據專案需求,需要將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"); } }