当前位置: 首页 > 科技观察

Java实现图像的高斯模糊和空间卷积

时间:2023-03-14 01:12:47 科技观察

高斯模糊(英文:GaussianBlur),又称高斯平滑,是AdobePhotoshop、GIMP、Paint.NET等图像处理软件中广泛使用的一种处理效果。它通常用于减少图像噪声和降低细节级别。通过这种虚化技术生成的图像,具有一种仿佛透过半透明屏幕观察图像的视觉效果,明显不同于镜头失焦的散景效果和普通照明阴影中的效果。高斯平滑也用于计算机视觉算法的预处理阶段,以增强图像在不同尺度下的图像效果。从数学的角度来看,图像的高斯模糊过程就是图像与正态分布的卷积。由于正态分布也称为高斯分布,因此这种技术称为高斯模糊。将图像与圆形框模糊进行卷积将产生更准确的散景效果。由于高斯函数的傅里叶变换是另一个高斯函数,所以高斯模糊是对图像的低通滤波器。高斯模糊使用高斯正态分布的密度函数来计算图像中每个像素的变换。根据一维高斯函数,可以推导出二维高斯函数:其中r为模糊半径,r^2=x^2+y^2,σ为正态分布的标准差。在二维中,此公式生成的曲面的轮廓是从中心正态分布的同心圆。由分布不为零的像素组成的卷积矩阵与原始图像进行变换。每个像素的值是周围相邻像素值的加权平均。原始像素的值具有最高的高斯分布值,因此具有最高的权重,并且随着与原始像素的距离越来越远,相邻像素的权重越来越小。与其他均衡模糊滤镜相比,以这种方式模糊可以更好地保留边缘效果。其实在iOS上实现高斯模糊是非常容易的。早在iOS5.0就有了CoreImageAPI,在CoreImage.framework库中,提供了大量的滤镜实现。+(UIImage*)coreBlurImage:(UIImage*)imagewithBlurNumber:(CGFloat)blur{CIContext*context=[CIContextcontextWithOptions:nil];CIImage*inputImage=[CIImageimageWithCGImage:image.CGImage];//设置过滤器CIFilter*filter=[CIFilterfilterWithName:@"CIGaussianBlur"];[filtersetValue:inputImageforKey:kCIInputImageKey];[filtersetValue:@(blur)forKey:@"inputRadius"];//模糊图像CIImage*result=[filtervalueForKey:kCIOutputImageKey];CGImageRefoutImage=[contextcreateCGImage:resultfromRect:[resultextent]];UIImage*blurImage=[UIImageimageWithCGImage:outImage];CGImageRelease(outImage);returnblurImage;}Android上的高斯模糊也可以使用原生API——RenderScript,但要求AndroidAPI在17以上,即Android4.2版本。/***使用RenderScript实现高级模型的算法*@parambitmap*@return*/publicBitmapblur(Bitmapbitmap){//让我们创建一个空位图,其大小与我们要模糊的位图相同BitmapoutBitmap=Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(),Bitmap.Config.ARGB_8888);//实例化一个新的RenderscriptRenderScriptrs=RenderScript.create(getApplicationContext());//使用渲染脚本创建一个内在模糊脚本ScriptIntrinsicBlurblurScript=ScriptIntrinsicBlur.create(rs,Element.U8_4(rs));//使用Renderscript和输入/输出位图创建分配(输入/输出)分配allIn=Allocation.createFromBitmap(rs,bitmap);分配allOut=Allocation.createFromBitmap(rs,outBitmap);//设置模糊的半径:0服务;publicGaussianBlurFilter(){kernel=newfloat[0];}publicvoidsetSigma(doublea){this.sigma=a;}@OverridepublicImageProcessorfilter(finalImageProcessorsrc){finalintwidth=src.getWidth();最终intheight=src.getHeight();最终整数大小=宽度*高度;intdims=src.getChannels();makeGaussianKernel(sigma,0.002,(int)Math.min(width,height));mExecutor=TaskUtils.newFixedThreadPool("cv4j",dims);service=newExecutorCompletionService<>(mExecutor);//保存结果for(inti=0;i(){publicVoidcall()抛出异常{byte[]inPixels=src.toByte(temp);byte[]temp=newbyte[size];模糊(像素、温度、宽度、高度);//H高斯模糊(temp,inPixels,height,width);//VGaussain返回空值;}});}for(inti=0;i这里是一维高斯,

**@paraminPixels*@paramoutPixels*@paramwidth*@paramheight*/privatevoidblur(byte[]inPixels,byte[]outPixels,intwidth,intheight){intsubCol=0;int索引=0,索引2=0;浮点数=0;intk=kernel.length-1;for(introw=0;row=宽度){subCol=0;}index2=行*宽度+子列;c=inPixels[index2]&0xff;sum+=c*kernel[Math.abs(m)];}outPixels[index]=(byte)Tools.clamp(sum);指数+=高度;}}}publicvoidmakeGaussianKernel(finaldoublesigma,finaldoubleaccuracy,intmaxRadius){intkRadius=(int)Math.ceil(sigma*Math.sqrt(-2*Math.log(accuracy)))+1;如果(最大半径<50)最大半径=50;//maxRadius太小会导致总和不准确。如果(kRadius>最大半径)kRadius=最大半径;kernel=newfloat[kRadius];for(inti=0;i