//=========================================================================== /// GetSaliencyMap /// /// Outputs a saliency map with a value assigned per pixel. The values are /// normalized in the interval [0,255] if normflag is set true (default value). //=========================================================================== void Saliency::GetSaliencyMap( const vector<UINT>& inputimg, const int& width, const int& height, vector<double>& salmap, const bool& normflag) { int sz = width*height; salmap.clear(); salmap.resize(sz); vector<double> lvec(0), avec(0), bvec(0); RGB2LAB(inputimg, lvec, avec, bvec); //-------------------------- // Obtain Lab average values //-------------------------- double avgl(0), avga(0), avgb(0); {for( int i = 0; i < sz; i++ ) { avgl += lvec[i]; avga += avec[i]; avgb += bvec[i]; }} avgl /= sz; avga /= sz; avgb /= sz; vector<double> slvec(0), savec(0), sbvec(0); //---------------------------------------------------- // The kernel can be [1 2 1] or [1 4 6 4 1] as needed. // The code below show usage of [1 2 1] kernel. //---------------------------------------------------- vector<double> kernel(0); kernel.push_back(1.0); kernel.push_back(2.0); kernel.push_back(1.0); GaussianSmooth(lvec, width, height, kernel, slvec); GaussianSmooth(avec, width, height, kernel, savec); GaussianSmooth(bvec, width, height, kernel, sbvec); {for( int i = 0; i < sz; i++ ) { salmap[i] = (slvec[i]-avgl)*(slvec[i]-avgl) + (savec[i]-avga)*(savec[i]-avga) + (sbvec[i]-avgb)*(sbvec[i]-avgb); }} if( true == normflag ) { vector<double> normalized(0); Normalize(salmap, width, height, normalized); swap(salmap, normalized); } }
/************************************************************************* * * \函数名称: * Canny() * * \输入参数: * unsigned char *pUnchImage- 图象数据 * int nWidth - 图象数据宽度 * int nHeight - 图象数据高度 * double sigma - 高斯滤波的标准方差 * double dRatioLow - 低阈值和高阈值之间的比例 * double dRatioHigh - 高阈值占图象象素总数的比例 * unsigned char *pUnchEdge - canny算子计算后的分割图 * * \返回值: * 无 * * \说明: * canny分割算子,计算的结果保存在pUnchEdge中,逻辑1(255)表示该点为 * 边界点,逻辑0(0)表示该点为非边界点。该函数的参数sigma,dRatioLow * dRatioHigh,是需要指定的。这些参数会影响分割后边界点数目的多少 ************************************************************************* */ void Canny(unsigned char *pUnchImage, int nWidth, int nHeight, double sigma, double dRatioLow, double dRatioHigh, unsigned char *pUnchEdge) { // 经过高斯滤波后的图象数据 unsigned char * pUnchSmooth ; // 指向x方向导数的指针 int * pnGradX ; // 指向y方向导数的指针 int * pnGradY ; // 梯度的幅度 int * pnGradMag ; pUnchSmooth = new unsigned char[nWidth*nHeight] ; pnGradX = new int [nWidth*nHeight] ; pnGradY = new int [nWidth*nHeight] ; pnGradMag = new int [nWidth*nHeight] ; // 对原图象进行滤波 GaussianSmooth(pUnchImage, nWidth, nHeight, sigma, pUnchSmooth) ; // 计算方向导数 DirGrad(pUnchSmooth, nWidth, nHeight, pnGradX, pnGradY) ; // 计算梯度的幅度 GradMagnitude(pnGradX, pnGradY, nWidth, nHeight, pnGradMag) ; // 应用non-maximum 抑制 NonmaxSuppress(pnGradMag, pnGradX, pnGradY, nWidth, nHeight, pUnchEdge) ; // 应用Hysteresis,找到所有的边界 Hysteresis(pnGradMag, nWidth, nHeight, dRatioLow, dRatioHigh, pUnchEdge); // 释放内存 delete pnGradX ; pnGradX = NULL ; delete pnGradY ; pnGradY = NULL ; delete pnGradMag ; pnGradMag = NULL ; delete pUnchSmooth ; pUnchSmooth = NULL ; }
// Canny算子 void Canny(LPBYTE pGray, SIZE sz, double sigma, double dRatLow, double dRatHigh, LPBYTE pResult) { //经过高斯滤波后的图像 LPBYTE pGaussSmooth; pGaussSmooth = new unsigned char[sz.cx*sz.cy]; //x方向导数的指针 int *pGradX; pGradX = new int[sz.cx*sz.cy]; //y方向 int *pGradY; pGradY = new int[sz.cx*sz.cy]; //梯度的幅度 int *pGradMag; pGradMag = new int[sz.cx*sz.cy]; //对原图高斯滤波 GaussianSmooth(sz,pGray,pGaussSmooth,sigma); //计算方向导数和梯度的幅度 Grad(sz,pGaussSmooth,pGradX,pGradY,pGradMag); //应用非最大抑制 NonmaxSuppress(pGradMag,pGradX,pGradY,sz,pResult); //应用Hysteresis,找到所有边界 Hysteresis(pGradMag,sz,dRatLow,dRatHigh,pResult); delete[] pGradX; pGradX = NULL; delete[] pGradY; pGradY = NULL; delete[] pGradMag; pGradMag = NULL; delete[] pGaussSmooth; pGaussSmooth = NULL; }
/******************************************************************************** 单尺度Retinex图像增强程序 sigma为高斯模糊标准差 scale为对比度系数 输入与输出均为r,g,b,gray *********************************************************************************/ void retinex(UINT8T* r, UINT8T* g, UINT8T* b, UINT8T* gray, int sigma, int scale) { //Retinex公式,Log(R(x, y)) = Log(I(x, y)) - Log(Gauss(I(x, y))) int i, j, k; //float src_fl[SIZE * 3]; //原图,量化结果图 //float src_fl1[SIZE * 3];//Log(I(x, y)) //float src_fl2[SIZE * 3];//Log(Gauss(I(x, y))) float* src_fl;//原图,量化结果图 float* src_fl1;//Log(I(x, y)) //float* src_fl2;//Log(Gauss(I(x, y))) float mean[3], dev[3]; //b,g,r float min[3]; float max[3]; float maxmin[3]; float temp1, temp2; //float[SIZE*3]的大数组赋值 src_fl = temp0_f; src_fl1 = temp1_f; //src_fl2 = temp2_f; //三维变一维, 并转换范围,所有图像元素增加1.0保证cvlog正常 for (i = 0; i < R; i++) for (j = 0; j < C; j++) { //+1从而避免log0 = -INF src_fl[i*C * 3 + j * 3] = (float)b[i*C+j]+1; src_fl[i*C * 3 + j * 3 + 1] = (float)g[i*C + j]+1; src_fl[i*C * 3 + j * 3 + 2] = (float)r[i*C + j]+1; } //计算Log(I(x, y)+1) for (i = 0; i < R; i++) for (j = 0; j < C; j++) for (k = 0; k < 3; k++) { src_fl1[i*C * 3 + j * 3 + k] = log(src_fl[i*C * 3 + j * 3 + k]); } //高斯模糊 //calc_gaussian_5x5(src_fl2, src_fl, 3); //GaussianSmooth(src_fl2, src_fl, sigma, 3); GaussianSmooth(src_fl, src_fl, sigma, 3); //计算Log(Gauss(I(x, y))) for (i = 0; i < R; i++) for (j = 0; j < C; j++) for (k = 0; k < 3; k++) src_fl[i*C * 3 + j * 3 + k] = log(src_fl[i*C * 3 + j * 3 + k]); //Log(R(x, y)) = Log(I(x, y)) - Log(Gauss(I(x, y))) for (i = 0; i < R; i++) for (j = 0; j < C; j++) for (k = 0; k < 3; k++) src_fl[i*C * 3 + j * 3 + k] = src_fl1[i*C * 3 + j * 3 + k] - src_fl[i*C * 3 + j * 3 + k]; //量化计算 //计算图像的均值、方差,SSR算法的核心之二 //使用GIMP中转换方法:使用图像的均值方差等信息进行变换 //没有添加溢出判断 AvgSdv(src_fl, mean, dev);//计算图像的均值和标准差 for (k = 0; k<3; k++) { min[k] = mean[k] - scale*dev[k]; max[k] = mean[k] + scale*dev[k]; maxmin[k] = max[k] - min[k]; } //量化 for (i = 0; i < R;i++) for (j = 0; j < C; j++) for (k = 0; k < 3; k++) { temp1 = 255 * (src_fl[i*C * 3 + j * 3 + k] - min[k]) / maxmin[k]; temp2 = temp1>255 ? 255 : temp1; src_fl[i*C * 3 + j * 3 + k] = temp2<0?0:temp2; } //转换结果 for (i = 0; i < R; i++) for (j = 0; j < C; j++) { b[i*C + j] = (UINT8T)src_fl[i*C * 3 + j * 3]; g[i*C + j] = (UINT8T)src_fl[i*C * 3 + j * 3 + 1]; r[i*C + j] = (UINT8T)src_fl[i*C * 3 + j * 3 + 2]; } /*for (int i = 0; i<src_fl2->width; i++) { for (int j = 0; j<src_fl2->height; j++) { data2[j*src_fl->widthStep / 4 + 3 * i + 0] = 255 * (data2[j*src_fl->widthStep / 4 + 3 * i + 0] - min[0]) / maxmin[0]; data2[j*src_fl->widthStep / 4 + 3 * i + 1] = 255 * (data2[j*src_fl->widthStep / 4 + 3 * i + 1] - min[1]) / maxmin[1]; data2[j*src_fl->widthStep / 4 + 3 * i + 2] = 255 * (data2[j*src_fl->widthStep / 4 + 3 * i + 2] - min[2]) / maxmin[2]; } } */ //计算预处理后的灰度图 calc_gray(); }
int Graph_Smooth( LCUI_Graph *src, LCUI_Graph *des, double sigma ) /* 对图像进行模糊处理 */ { return GaussianSmooth( src, des, sigma ); }
int main() { /*----------------------------Part 1------------------------------------*/ int ysize = 342; int xsize = 546; int padding = 1; float **inImage = ImageInit(xsize, ysize); float **padImage = ImageInit(xsize + 2*padding, ysize + 2*padding); float **sobelImage = ImageInit(xsize, ysize); float **threshImage = ImageInit(xsize, ysize); OpenImage("porsche", xsize, ysize, inImage); PadImage(inImage, padImage, xsize, ysize, padding); Sobel(padImage, sobelImage, xsize + 2*padding, ysize + 2*padding); SaveImage("porsche", "_sobel", xsize, ysize, sobelImage); BinThresh(sobelImage, threshImage, xsize, ysize, 60); SaveImage("porsche", "_thresh60", xsize, ysize, threshImage); ysize = 256; xsize = 256; OpenImage("mri", xsize, ysize, inImage); PadImage(inImage, padImage, xsize, ysize, padding); Sobel(padImage, sobelImage, xsize + 2 * padding, ysize + 2 * padding); SaveImage("mri", "_sobel", xsize, ysize, sobelImage); BinThresh(sobelImage, threshImage, xsize, ysize, 50); SaveImage("mri", "_thresh50", xsize, ysize, threshImage); free(inImage); free(padImage); free(sobelImage); free(threshImage); /*----------------------------Part 2------------------------------------*/ xsize = ysize = 256; float **circImage = ImageInit(xsize, ysize); float **padCirc = ImageInit(xsize + 2 * padding, ysize + 2 * padding); float **sobelCirc = ImageInit(xsize, ysize); float **threshCirc = ImageInit(xsize, ysize); float **noiseCirc = ImageInit(xsize, ysize); float **padNoiseCirc = ImageInit(xsize + 2 * padding, ysize + 2 * padding); float **sobelNoiseCirc = ImageInit(xsize, ysize); float **noiseGaussCirc = ImageInit(xsize, ysize); float **padNoiseGaussCirc = ImageInit(xsize + 2 * padding, ysize + 2 * padding); float **sobelNoiseGaussCirc = ImageInit(xsize, ysize); float **sobelNoiseGaussThreshCirc = ImageInit(xsize, ysize); float **test = ImageInit(xsize + 2, ysize +2); int c = 256 / 2 - 1; CreateCircle(circImage, ysize, xsize, c, c, 50, 60); CreateCircle(circImage, ysize, xsize, c, c, 50, 40); CreateCircle(circImage, ysize, xsize, c, c, 50, 20); SaveImage("circles", "", xsize, ysize, circImage); PadImage(circImage, padCirc, xsize, ysize, padding); Sobel(padCirc, sobelCirc, xsize + 2 * padding, ysize + 2 * padding); SaveImage("circles", "_sobel", xsize, ysize, sobelCirc); BinThresh(sobelCirc, threshCirc, xsize, ysize, 100); SaveImage("circles", "_thresh100", xsize, ysize, threshCirc); // Noise = 10 AddUniNoise(circImage, noiseCirc, xsize, ysize, 10); SaveImage("circles", "_noise10", xsize, ysize, noiseCirc); PadImage(noiseCirc, padNoiseCirc, xsize, ysize, padding); Sobel(padNoiseCirc, sobelNoiseCirc, xsize + 2 * padding, ysize + 2 * padding); BinThresh(sobelNoiseCirc, sobelNoiseCirc, xsize, ysize, 100); SaveImage("circles", "_noise_sobel10", xsize, ysize, sobelNoiseCirc); AccuracyReport(threshCirc, sobelNoiseCirc, xsize, ysize); GaussianSmooth(padNoiseCirc, noiseGaussCirc, xsize + 2 * padding, ysize + 2 * padding); SaveImage("circles", "_noise_gauss10", xsize, ysize, noiseGaussCirc); PadImage(noiseGaussCirc, padNoiseGaussCirc, xsize, ysize, padding); Sobel(padNoiseGaussCirc, sobelNoiseGaussCirc, xsize + 2 * padding, ysize + 2 * padding); BinThresh(sobelNoiseGaussCirc, sobelNoiseGaussThreshCirc, xsize, ysize, 100); SaveImage("circles", "_noise_sobel_gauss_thresh10", xsize, ysize, sobelNoiseGaussThreshCirc); AccuracyReport(threshCirc, sobelNoiseGaussThreshCirc, xsize, ysize); // Noise = 50 AddUniNoise(circImage, noiseCirc, xsize, ysize, 50); SaveImage("circles", "_noise50", xsize, ysize, noiseCirc); PadImage(noiseCirc, padNoiseCirc, xsize, ysize, padding); Sobel(padNoiseCirc, sobelNoiseCirc, xsize + 2 * padding, ysize + 2 * padding); BinThresh(sobelNoiseCirc, sobelNoiseCirc, xsize, ysize, 100); SaveImage("circles", "_noise_sobel50", xsize, ysize, sobelNoiseCirc); AccuracyReport(threshCirc, sobelNoiseCirc, xsize, ysize); GaussianSmooth(padNoiseCirc, noiseGaussCirc, xsize + 2 * padding, ysize + 2 * padding); SaveImage("circles", "_noise_gauss50", xsize, ysize, noiseGaussCirc); PadImage(noiseGaussCirc, padNoiseGaussCirc, xsize, ysize, padding); Sobel(padNoiseGaussCirc, sobelNoiseGaussCirc, xsize + 2 * padding, ysize + 2 * padding); BinThresh(sobelNoiseGaussCirc, sobelNoiseGaussThreshCirc, xsize, ysize, 100); SaveImage("circles", "_noise_sobel_gauss_thresh50", xsize, ysize, sobelNoiseGaussThreshCirc); AccuracyReport(threshCirc, sobelNoiseGaussThreshCirc, xsize, ysize); // Noise = 100 AddUniNoise(circImage, noiseCirc, xsize, ysize, 100); SaveImage("circles", "_noise100", xsize, ysize, noiseCirc); PadImage(noiseCirc, padNoiseCirc, xsize, ysize, padding); Sobel(padNoiseCirc, sobelNoiseCirc, xsize + 2 * padding, ysize + 2 * padding); BinThresh(sobelNoiseCirc, sobelNoiseCirc, xsize, ysize, 100); SaveImage("circles", "_noise_sobel100", xsize, ysize, sobelNoiseCirc); AccuracyReport(threshCirc, sobelNoiseCirc, xsize, ysize); GaussianSmooth(padNoiseCirc, noiseGaussCirc, xsize + 2 * padding, ysize + 2 * padding); SaveImage("circles", "_noise_gauss100", xsize, ysize, noiseGaussCirc); PadImage(noiseGaussCirc, padNoiseGaussCirc, xsize, ysize, padding); Sobel(padNoiseGaussCirc, sobelNoiseGaussCirc, xsize + 2 * padding, ysize + 2 * padding); BinThresh(sobelNoiseGaussCirc, sobelNoiseGaussThreshCirc, xsize, ysize, 100); SaveImage("circles", "_noise_sobel_gauss_thresh100", xsize, ysize, sobelNoiseGaussThreshCirc); AccuracyReport(threshCirc, sobelNoiseGaussThreshCirc, xsize, ysize); free(circImage); free(padCirc); free(sobelCirc); free(threshCirc); free(noiseCirc); free(padNoiseCirc); free(sobelNoiseCirc); free(noiseGaussCirc); free(padNoiseGaussCirc); free(sobelNoiseGaussCirc); free(sobelNoiseGaussThreshCirc); return 0; }
/******************************************************************************** 单尺度Retinex图像增强程序 src为待处理图像 sigma为高斯模糊标准差 scale为对比度系数 *********************************************************************************/ void retinex(RGBTYPE* dst, RGBTYPE* src, int sigma, int scale) { //Retinex公式,Log(R(x, y)) = Log(I(x, y)) - Log(Gauss(I(x, y))) int i, j,k; //double src_fl[SIZE * 3]; //原图,量化结果图 //double src_fl1[SIZE * 3];//Log(I(x, y)) //double src_fl2[SIZE * 3];//Log(Gauss(I(x, y))) double* src_fl;//原图,量化结果图 double* src_fl1;//Log(I(x, y)) double* src_fl2;//Log(Gauss(I(x, y))) double mean[3], dev[3]; //b,g,r double min[3]; double max[3]; double maxmin[3]; double temp1, temp2; src_fl = (double*)malloc(sizeof(double)*SIZE*3); src_fl1 = (double*)malloc(sizeof(double)*SIZE*3); src_fl2 = (double*)malloc(sizeof(double)*SIZE*3); //三维变一维, 并转换范围,所有图像元素增加1.0保证cvlog正常 for (i = 0; i < R; i++) for (j = 0; j < C; j++) { //+1从而避免log0 = -INF src_fl[i*C * 3 + j * 3] = (double)src[i*C+j].b+1; src_fl[i*C * 3 + j * 3 + 1] = (double)src[i*C + j].g+1; src_fl[i*C * 3 + j * 3 + 2] = (double)src[i*C + j].r+1; } //计算Log(I(x, y)+1) for (i = 0; i < R; i++) for (j = 0; j < C; j++) for (k = 0; k < 3; k++) { src_fl1[i*C * 3 + j * 3 + k] = log(src_fl[i*C * 3 + j * 3 + k]); } //高斯模糊 //calc_gaussian_5x5(src_fl2, src_fl, 3); GaussianSmooth(src_fl2, src_fl, sigma, 3); //计算Log(Gauss(I(x, y))) for (i = 0; i < R; i++) for (j = 0; j < C; j++) for (k = 0; k < 3; k++) src_fl2[i*C * 3 + j * 3 + k] = log(src_fl2[i*C * 3 + j * 3 + k]); //Log(R(x, y)) = Log(I(x, y)) - Log(Gauss(I(x, y))) for (i = 0; i < R; i++) for (j = 0; j < C; j++) for (k = 0; k < 3; k++) src_fl[i*C * 3 + j * 3 + k] = src_fl1[i*C * 3 + j * 3 + k] - src_fl2[i*C * 3 + j * 3 + k]; //量化计算 //计算图像的均值、方差,SSR算法的核心之二 //使用GIMP中转换方法:使用图像的均值方差等信息进行变换 //没有添加溢出判断 AvgSdv(src_fl, mean, dev);//计算图像的均值和标准差 for (k = 0; k<3; k++) { min[k] = mean[k] - scale*dev[k]; max[k] = mean[k] + scale*dev[k]; maxmin[k] = max[k] - min[k]; } //量化 for (i = 0; i < R;i++) for (j = 0; j < C; j++) for (k = 0; k < 3; k++) { temp1 = 255 * (src_fl[i*C * 3 + j * 3 + k] - min[k]) / maxmin[k]; temp2 = temp1>255 ? 255 : temp1; src_fl[i*C * 3 + j * 3 + k] = temp2<0?0:temp2; } //转换结果 for (i = 0; i < R; i++) for (j = 0; j < C; j++) { dst[i*C + j].b = (UINT8T)src_fl[i*C * 3 + j * 3]; dst[i*C + j].g = (UINT8T)src_fl[i*C * 3 + j * 3 + 1]; dst[i*C + j].r = (UINT8T)src_fl[i*C * 3 + j * 3 + 2]; } /*for (int i = 0; i<src_fl2->width; i++) { for (int j = 0; j<src_fl2->height; j++) { data2[j*src_fl->widthStep / 4 + 3 * i + 0] = 255 * (data2[j*src_fl->widthStep / 4 + 3 * i + 0] - min[0]) / maxmin[0]; data2[j*src_fl->widthStep / 4 + 3 * i + 1] = 255 * (data2[j*src_fl->widthStep / 4 + 3 * i + 1] - min[1]) / maxmin[1]; data2[j*src_fl->widthStep / 4 + 3 * i + 2] = 255 * (data2[j*src_fl->widthStep / 4 + 3 * i + 2] - min[2]) / maxmin[2]; } } */ free(src_fl); free(src_fl1); free(src_fl2); }
/** 对图像进行模糊处理 */ LCUI_API int Graph_Smooth( LCUI_Graph *src, LCUI_Graph *des, double sigma ) { return GaussianSmooth( src, des, sigma ); }