图像马赛克原理及实现

        图像打码其实也是图像卷积操作中,空间域滤波的一种方式,用一定大小的滤波器对马赛克范围内像素进行操作。实现过程:将需要打马范围按照滤波器大小划分为多个区块,取滤波器范围内像素,求取均值,再将均值赋值给范围内每一个像素,滤波器再滑到下一个区块。从原理上看,图像马赛克特效非常简单,下面就来看一下具体实现过程。

        对整张图像打码。对整张图片打码也叫做像素格特效,我们只需要考虑滤波器大小即可。

        代码:

/**
	 * 对整个图片打码
	 * @param image
	 * @param length 马赛克大小
	 */
public void imageMosaic(BufferedImage image,int length) {
		int width = image.getWidth();
		int height = image.getHeight();
		int size = length * length;
		int x = width / length;
		int y = height / length;
		for(int i = 0; i < x; i++) {
			for(int j = 0; j < y; j++) {
				int R=0,G=0,B=0;
				for(int m = 0; m < length; m++) {
					for(int n = 0; n < length; n++) {
						int xCoordinate = i * length + m;
						int yCoordinate = j * length + n;
						int rgb = image.getRGB(xCoordinate, yCoordinate);
						R += (rgb >> 16) & 0xff;
						G += (rgb >> 8) & 0xff;
						B += rgb & 0xff;
					}
				}
				R = R / size;
				G = G / size;
				B = B / size;
				int RGB = (255 & 0xff) << 24 | (clamp(R) & 0xff) << 16 | (clamp(G) & 0xff) << 8 | (clamp(B) & 0xff);
				for(int m = 0; m < length; m++) {
					for(int n = 0; n < length; n++) {
						int xCoordinate = i * length + m;
						int yCoordinate = j * length + n;
						image.setRGB(xCoordinate, yCoordinate, RGB);
					}
				}
			}
		}
	}

局部打码。局部打码需要先定义好打码起始位置,打码范围,马赛克大小。

代码:

/**
	 * 局部打码
	 * @param image
	 * @param xCoordinate 横坐标起始位置
	 * @param yCoordinate 纵坐标起始位置
	 * @param xLength     x方向长度
	 * @param yLength     y方向长度
	 * @param length      马赛克大小
	 */
	public void mosaic(BufferedImage image,int xCoordinate,int yCoordinate,int xLength,int yLength,int length) {
		if ((xCoordinate + xLength) > image.getWidth() || (yCoordinate + yLength) > image.getHeight()) {
			System.out.println("马赛克范围大于图像范围!");
			return;
		}
		int size = length * length;
		int x = xLength / length;
		int y = yLength / length;
		for(int m = 0; m < x; m++) {
			for(int n = 0; n < y; n++) {
				int R=0,G=0,B=0;
				for(int i = 0; i < length; i++) {
					for(int j = 0; j < length; j++) {
						int x1 = xCoordinate + m * length + i;
						int y1 = yCoordinate + n * length + j;
						int rgb = image.getRGB(x1, y1);
						R += (rgb >> 16) & 0xff;
						G += (rgb >> 8) & 0xff;
						B += rgb & 0xff;
					}
				}
				R = R / size;
				G = G / size;
				B = B / size;
				int RGB = (255 & 0xff) << 24 | (clamp(R) & 0xff) << 16 | (clamp(G) & 0xff) << 8 | (clamp(B) & 0xff);
				for(int i = 0; i < length; i++) {
					for(int j = 0; j < length; j++) {
						int x1 = xCoordinate + m * length + i;
						int y1 = yCoordinate + n * length + j;
						image.setRGB(x1, y1, RGB);
					}
				}
			}
		}
	}

        完整的马赛克实现代码:

public class MosaicFilter {
	/**
	 * 对整个图片打码
	 * @param image
	 * @param length 马赛克大小
	 */
	public void imageMosaic(BufferedImage image,int length) {
		int width = image.getWidth();
		int height = image.getHeight();
		int size = length * length;
		int x = width / length;
		int y = height / length;
		for(int i = 0; i < x; i++) {
			for(int j = 0; j < y; j++) {
				int R=0,G=0,B=0;
				for(int m = 0; m < length; m++) {
					for(int n = 0; n < length; n++) {
						int xCoordinate = i * length + m;
						int yCoordinate = j * length + n;
						int rgb = image.getRGB(xCoordinate, yCoordinate);
						R += (rgb >> 16) & 0xff;
						G += (rgb >> 8) & 0xff;
						B += rgb & 0xff;
					}
				}
				R = R / size;
				G = G / size;
				B = B / size;
				int RGB = (255 & 0xff) << 24 | (clamp(R) & 0xff) << 16 | (clamp(G) & 0xff) << 8 | (clamp(B) & 0xff);
				for(int m = 0; m < length; m++) {
					for(int n = 0; n < length; n++) {
						int xCoordinate = i * length + m;
						int yCoordinate = j * length + n;
						image.setRGB(xCoordinate, yCoordinate, RGB);
					}
				}
			}
		}
	}

	/**
	 * 局部打码
	 * @param image
	 * @param xCoordinate 横坐标起始位置
	 * @param yCoordinate 纵坐标起始位置
	 * @param xLength     x方向长度
	 * @param yLength     y方向长度
	 * @param length      马赛克大小
	 */
	public void mosaic(BufferedImage image,int xCoordinate,int yCoordinate,int xLength,int yLength,int length) {
		if ((xCoordinate + xLength) > image.getWidth() || (yCoordinate + yLength) > image.getHeight()) {
			System.out.println("马赛克范围大于图像范围!");
			return;
		}
		int size = length * length;
		int x = xLength / length;
		int y = yLength / length;
		for(int m = 0; m < x; m++) {
			for(int n = 0; n < y; n++) {
				int R=0,G=0,B=0;
				for(int i = 0; i < length; i++) {
					for(int j = 0; j < length; j++) {
						int x1 = xCoordinate + m * length + i;
						int y1 = yCoordinate + n * length + j;
						int rgb = image.getRGB(x1, y1);
						R += (rgb >> 16) & 0xff;
						G += (rgb >> 8) & 0xff;
						B += rgb & 0xff;
					}
				}
				R = R / size;
				G = G / size;
				B = B / size;
				int RGB = (255 & 0xff) << 24 | (clamp(R) & 0xff) << 16 | (clamp(G) & 0xff) << 8 | (clamp(B) & 0xff);
				for(int i = 0; i < length; i++) {
					for(int j = 0; j < length; j++) {
						int x1 = xCoordinate + m * length + i;
						int y1 = yCoordinate + n * length + j;
						image.setRGB(x1, y1, RGB);
					}
				}
			}
		}
	}
	
	// 判断r,g,b值,大于256返回256,小于0则返回0,0到256之间则直接返回原始值
	private int clamp(int rgb) {
		if (rgb > 255)
			return 255;
		if (rgb < 0)
			return 0;
		return rgb;
	}
	
	public static void main(String[] args) throws Exception{
		File in = new File("C:/Users/admin/Desktop/1.jpg");
		File out = new File("C:/Users/admin/Desktop/3.jpg");
		BufferedImage image = ImageIO.read(in);
		new MosaicFilter().imageMosaic(image, 5);
		//new MosaicFilter().mosaic(image, 100, 70, 50, 50,10);
		ImageIO.write(image, "jpg", out);
	}
}

          原图:

        全局打码:

        局部打码:

       

 

 

 

 

 

  • 5
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TheMatrixs

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值