图像处理之背景虚化

来源:互联网 发布:哪些高校有网络教育 编辑:程序博客网 时间:2024/05/01 22:00

废话不多说,先上图。

原图


圆形的清晰区域


竖直的清晰区域


水平的清晰区域


嘿嘿,看上去还可以哈~~我们这里说的背景虚化呢,自然没有能力做到自动识别背景与前景的,所以只能算是一个半自动的过程:由用户来指定哪片区域是清晰的,哪片区域是模糊的,然后在清晰的区域与模糊的区域之间做一个简单的过渡。

我们在这里提供了三张模式,分别是圆形的清晰区域,竖直的清晰区域和水平的清晰区域。示意图如下所示

圆形


横向


纵向


如果你还想折腾出其他的形状,可以参考我后面的代码自己折腾一下。

这里不打算讲高斯模糊之类的东西,相信现有的博客写高斯模糊早已写烂了。我也只是借用了图像模糊里面的一个思想而已:使用周围像素的平均值来代替当前像素。高斯模糊里面对像素点周围不同位置的像素点还赋予了不同的权重,我为了简单,索性让所有的权重都一样。产生的效果也还行。

下面就把全部代码都奉上。


package algorithm.blur;import java.awt.Color;import java.awt.image.BufferedImage;public class InteractiveBlur{// 掩码最小值public static final int MIN_MASK_SIZE = 3;// 掩码最大值public static final int MAX_MASK_SIZE = 15;//掩码最大值的一半public static final int HALF_MAX_MASK_SIZE = 7;// 最小值与最大值的差public static final int DIFF_MASK_SIZE = MAX_MASK_SIZE - MIN_MASK_SIZE;// 点在模糊区域中public static final int AREA_BLUR = 1;// 点在清晰区域中public static final int AREA_CLEAR = 2;// 点在过渡区域中public static final int AREA_TRAN = 3;// 圆形的清晰区域public static final int TYPE_CIRCLE = 1;// 垂直的清晰区域public static final int TYPE_VERTCIAL = 2;// 水平的清晰区域public static final int TYPE_HORIZONTAL = 3;//外部区域以外的都是模糊的private static int outSize;//内部区域以内的都是清晰的private static int innerSize;//区域private static int area;private static Color[][] colorMatrix;/** * 获取图像 *  * @param image *            源图像 * @param x *            x坐标 * @param y *            y坐标 * @param size *            作用范围 * @param type *            类型 * */public static BufferedImage getImage(BufferedImage image, int x, int y, int size, int type){InteractiveBlur.innerSize = size;InteractiveBlur.outSize = (int) (size * 1.5);// 获取rgb矩阵colorMatrix = getColorMatrix(image);switch (type){case TYPE_VERTCIAL:return getVecticalImage(image, x, size);case TYPE_HORIZONTAL:return getHozizontalImage(image, y, size);default:return getCircleImage(image, x, y, size);}}/** * 获取圆形的清晰区域 *  * @param image *            源图像 * @param x *            x坐标 * @param y *            y坐标 * @param size *            作用范围 * */private static BufferedImage getCircleImage(BufferedImage image, int centerX, int centerY, int size){int width = image.getWidth();int height = image.getHeight();BufferedImage outputImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);for (int y = HALF_MAX_MASK_SIZE; y < height - HALF_MAX_MASK_SIZE; y++){for (int x = HALF_MAX_MASK_SIZE; x < width - HALF_MAX_MASK_SIZE; x++){int distance = getDistance(x, y, centerX, centerY);area = getArea(distance);outputImage.setRGB(x, y, getRGBValue(image, x, y,distance));}}return outputImage;}/** * 获取纵向的背景虚化图像 *  * @param image *            源图像 * @param x *            x坐标 * @param y *            y坐标 * @param size *            作用范围 * */public static BufferedImage getVecticalImage(BufferedImage image, int centerX, int size){int width = image.getWidth();int height = image.getHeight();BufferedImage outputImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);for (int x = HALF_MAX_MASK_SIZE; x < width - HALF_MAX_MASK_SIZE; x++){int distance  = Math.abs(x - centerX);area = getArea(Math.abs(x - centerX));for (int y = HALF_MAX_MASK_SIZE; y < height - HALF_MAX_MASK_SIZE; y++){outputImage.setRGB(x, y, getRGBValue(image, x, y,distance));}}return outputImage;}/** * 获取水平的背景虚化图像 *  * @param image *            源图像 * @param x *            x坐标 * @param y *            y坐标 * @param size *            作用范围 * */public static BufferedImage getHozizontalImage(BufferedImage image, int centerY, int size){int width = image.getWidth();int height = image.getHeight();BufferedImage outputImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);for (int y = HALF_MAX_MASK_SIZE; y < height - HALF_MAX_MASK_SIZE; y++){int distance = Math.abs(y - centerY);area = getArea(distance);for (int x = HALF_MAX_MASK_SIZE; x < width - HALF_MAX_MASK_SIZE; x++){outputImage.setRGB(x, y, getRGBValue(image, x, y,distance));}}return outputImage;}private static int getRGBValue(BufferedImage image, int x, int y,int distance){if (area == AREA_BLUR){return getBlurRGBValue(x, y, MAX_MASK_SIZE);}else if (area == AREA_TRAN){// 过渡区间int maskSize = MIN_MASK_SIZE + DIFF_MASK_SIZE * (distance - innerSize) / (outSize - innerSize);// 将masksize变为奇数maskSize = (maskSize / 2) * 2 + 1;return getBlurRGBValue(x, y, maskSize);}else{return image.getRGB(x, y);}}/** * 获取模糊后的图像的rgb值 *  * @param colorMatrix * @param x * @param y * @param maskSize * */private static int getBlurRGBValue(int x, int y, int maskSize){int sum = maskSize * maskSize;int halfMaskSize = maskSize / 2;int sumR = 0, sumG = 0, sumB = 0;for (int i = -halfMaskSize; i <= halfMaskSize; i++){for (int j = -halfMaskSize; j <= halfMaskSize; j++){sumR += colorMatrix[x + i][y + j].getRed();sumG += colorMatrix[x + i][y + j].getGreen();sumB += colorMatrix[x + i][y + j].getBlue();}}sumR /= sum;sumG /= sum;sumB /= sum;sumR = sumR << 16;sumG = sumG << 8;return sumR|sumG|sumB;}// 判断点在那个区域private static int getArea(int distance){int area;if (distance > outSize){area = AREA_BLUR;}else if (distance < innerSize){area = AREA_CLEAR;}else{area = AREA_TRAN;}return area;}/** * 获取两点之间的距离 *  * @param x1 *            第一个点的X坐标 * @param y1 *            第一个点的y坐标 * @param x2 *            第二个点的X坐标 * @param y2 *            第二个点的y坐标 * */private static int getDistance(int x1, int y1, int x2, int y2){int x = x1 - x2;int y = y1 - y2;return (int) Math.sqrt(x * x + y * y);}/** * 获取图像的color矩阵 *  * @param image * */private static Color[][] getColorMatrix(BufferedImage image){int width = image.getWidth();int height = image.getHeight();Color[][] matrix = new Color[width][height];for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){matrix[x][y]  = new Color(image.getRGB(x, y));}}return matrix;}}

                                             
1 0
原创粉丝点击