图像处理之基于像素的图像混合

简介: 图像处理之基于像素的图像混合

介绍几种常见的将两张图像混合在一起形成一张新的图像的算法,


首先看一下下面算法演示中要使用的两张图像:

1354118110_3712.jpg

1354118125_9845.jpg


为了得到更好的混合效果,我选择了两张一样大小的图片。


方法一:


通过简单对于像素点的像素相乘得到输出像素值,代码演示如下:



private int modeOne(int v1, int v2) {
  return (v1 * v2) / 255;
}

方法一的效果如下:

1354119244_6100.jpg


方法二:

通过计算两个像素之和再减去方法一的输出值,代码如下:



private int modeTwo(int v1, int v2) {
  return v1 + v2 - v1 * v2 / 255;
}

方法二的效果如下:

1354119268_5607.jpg



方法三:

通过像素值128这个特殊的中值来求取输出值,代码如下:


private int modeThree(int v1, int v2) {
  return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
}

方法三的效果如下:


1354119298_1895.jpg


方法四:


与方法三不同,中值127.5被用在计算等式中,代码如下:



private int modeFour(double v1, double v2) {
  if ( v1 > 127.5 ){
      return (int)(v2 + (255.0 - v2) * ((v1 - 127.5) / 127.5) * (0.5 - Math.abs(v2-127.5)/255.0));
   }else{
      return (int)(v2 - v2 * ((127.5 -  v1) / 127.5) * (0.5 - Math.abs(v2-127.5)/255.0));
   }
}

方法四的效果如下:

1354119320_3389.jpg



方法五:

中值计算考虑,是方法一的升级版本,使得混合更加精细,代码如下:



private int modeFive(double v1, double v2) {
  if ( v1 > 127.5 ){
      return (int)(v2 + (255.0 - v2) * ((v1 - 127.5) / 127.5));
   }else{
      return (int)(v2 * v1 / 127.5);
   }
}

方法五的效果如下:


1354119348_4269.jpg


滤镜源代码如下:


package com.gloomyfish.filter.study;
import java.awt.image.BufferedImage;
/***
 * i get these blend method from html5 demo then i decide to 
 * translate these java script methods into java
 * 偶尔我也会写中文注释, 常见的图像混合方法
 * @author fish
 * @date 2012-11-28
 */
public class ImageBlendFilter extends AbstractBufferedImageOp {
  /** Define the blend mode */
  public final static int MULTIPLY_PIXEL = 1;
  public final static int SCREEN_PIXEL = 2;
  public final static int OVERLAY_PIXEL = 3;
  public final static int SOFTLIGHT_PIXEL = 4;
  public final static int HARDLIGHT_PIXEL = 5;
  private int mode;
  private BufferedImage secondImage;
  public ImageBlendFilter() {
  mode = 1;
  }
  public void setBlendMode(int mode) {
  this.mode = mode;
  }
  public void setSecondImage(BufferedImage image) {
  this.secondImage = image;
  }
  @Override
  public BufferedImage filter(BufferedImage src, BufferedImage dest) {
  checkImages(src);
  int width = src.getWidth();
        int height = src.getHeight();
        if ( dest == null )
          dest = createCompatibleDestImage( src, null );
        int[] input1 = new int[width*height];
        int[] input2 = new int[secondImage.getWidth() * secondImage.getHeight()];
        int[] outPixels = new int[width*height];
        getRGB( src, 0, 0, width, height, input1);
        getRGB( secondImage, 0, 0, secondImage.getWidth(), secondImage.getHeight(), input2);
        int index = 0;
        int ta1 = 0, tr1 = 0, tg1 = 0, tb1 = 0;
        for(int row=0; row<height; row++) {
          for(int col=0; col<width; col++) {
          index = row * width + col;
          ta1 = (input1[index] >> 24) & 0xff;
                tr1 = (input1[index] >> 16) & 0xff;
                tg1 = (input1[index] >> 8) & 0xff;
                tb1 = input1[index] & 0xff;
                int[] rgb = getBlendData(tr1, tg1, tb1, input2, row, col);
                outPixels[index] = (ta1 << 24) | (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
               
          }
        }
        setRGB( dest, 0, 0, width, height, outPixels );
        return dest;
  }
  private int[] getBlendData(int tr1, int tg1, int tb1, int[] input,int row, int col) {
  int width = secondImage.getWidth();
        int height = secondImage.getHeight();
        if(col >= width || row >= height) {
          return new int[]{tr1, tg1, tb1};
        }
        int index = row * width + col;
  // int ta = (input[index] >> 24) & 0xff;
        int tr = (input[index] >> 16) & 0xff;
        int tg = (input[index] >> 8) & 0xff;
        int tb = input[index] & 0xff;
        int[] rgb = new int[3];
        if(mode == 1) {
          rgb[0] = modeOne(tr1, tr);
          rgb[1] = modeOne(tg1, tg);
          rgb[2] = modeOne(tb1, tb);
        }
        else if(mode == 2) {
          rgb[0] = modeTwo(tr1, tr);
          rgb[1] = modeTwo(tg1, tg);
          rgb[2] = modeTwo(tb1, tb);          
        }
        else if(mode == 3) {
          rgb[0] = modeThree(tr1, tr);
          rgb[1] = modeThree(tg1, tg);
          rgb[2] = modeThree(tb1, tb);          
        }
        else if(mode == 4) {
          rgb[0] = modeFour(tr1, tr);
          rgb[1] = modeFour(tg1, tg);
          rgb[2] = modeFour(tb1, tb);         
        }
        else if(mode == 5) {
          rgb[0] = modeFive(tr1, tr);
          rgb[1] = modeFive(tg1, tg);
          rgb[2] = modeFive(tb1, tb);         
        }
        return rgb;
  }
  private int modeOne(int v1, int v2) {
  return (v1 * v2) / 255;
  }
  private int modeTwo(int v1, int v2) {
  return v1 + v2 - v1 * v2 / 255;
  }
  private int modeThree(int v1, int v2) {
  return (v2 < 128) ? (2 * v1 * v2 / 255):(255 - 2 * (255 - v1) * (255 - v2) / 255);
  }
  private int modeFour(double v1, double v2) {
      if ( v1 > 127.5 ){
          return (int)(v2 + (255.0 - v2) * ((v1 - 127.5) / 127.5) * (0.5 - Math.abs(v2-127.5)/255.0));
       }else{
          return (int)(v2 - v2 * ((127.5 -  v1) / 127.5) * (0.5 - Math.abs(v2-127.5)/255.0));
       }
  }
  private int modeFive(double v1, double v2) {
      if ( v1 > 127.5 ){
          return (int)(v2 + (255.0 - v2) * ((v1 - 127.5) / 127.5));
       }else{
          return (int)(v2 * v1 / 127.5);
       }
  }
  private void checkImages(BufferedImage src) {
  int width = src.getWidth();
        int height = src.getHeight();
  if(secondImage == null || secondImage.getWidth() > width || secondImage.getHeight() > height) {
    throw new IllegalArgumentException("the width, height of the input image must be great than blend image");
  }
  }
}

如果觉得效果很有趣,请顶一下,谢谢!


转载文章请注明

相关文章
|
9月前
|
机器学习/深度学习 传感器 算法
【交互式阈值二进制图像】采用彩色或单色图像通过交互/手动方式阈值单色图像或彩色图像的单个色带研究(Matlab代码实现)
【交互式阈值二进制图像】采用彩色或单色图像通过交互/手动方式阈值单色图像或彩色图像的单个色带研究(Matlab代码实现)
|
16天前
|
算法 API 计算机视觉
图像处理之角点检测与亚像素角点定位
图像处理之角点检测与亚像素角点定位
14 1
|
17天前
|
算法 计算机视觉
图像处理之图像快速旋转算法
图像处理之图像快速旋转算法
15 1
|
16天前
|
算法 计算机视觉
图像处理之错切变换
图像处理之错切变换
10 1
|
17天前
|
资源调度 计算机视觉
图像处理之图像加噪
图像处理之图像加噪
7 0
图像处理之图像加噪
|
17天前
|
算法 C语言 计算机视觉
图像处理之图像快速插值放缩算法
图像处理之图像快速插值放缩算法
17 0
|
1月前
|
计算机视觉 索引
【OpenCV】—ROI区域图像叠加&图像混合
【OpenCV】—ROI区域图像叠加&图像混合
|
1月前
|
前端开发 计算机视觉 C++
【OpenCV】—分离颜色通道、多通道图像混合
【OpenCV】—分离颜色通道、多通道图像混合
|
机器学习/深度学习 算法 数据挖掘
传统图像处理之颜色特征
传统图像处理之颜色特征
187 0
传统图像处理之颜色特征
|
机器学习/深度学习 编解码 人工智能
图像基础二(下)
图像基础二(下)
155 0
图像基础二(下)