java版高斯算法-模糊图片

package com.yr.feiyu.common.util;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
/**
 * 
 * <p class="detail">
 * 描述:高斯模糊
 * </p>
 * @ClassName: GaussianBlurUtil
 * @version V1.0  
 * @date 2016年4月20日 
 * @author <a href="mailto:1435290472@qq.com">zq</a>
 */
public class GaussianBlurUtil {
 
 public static void main(String[] args) throws IOException {
  BufferedImage img = ImageIO.read(new File("e:/c.jpeg"));
  long start = System.currentTimeMillis();
  img = blur(img, 170);
  long end = System.currentTimeMillis();
  ImageIO.write(img, "jpeg", new File("e:/test.jpeg"));//保存为test.jpeg文件
  System.out.println("花费时间:"+(end-start));
  System.out.println("success");
 }
 
 /**
  * 
  * <p class="detail">
  * 功能:模糊执行方法
  * </p>
  * @date 2016年4月20日
  * @author <a href="mailto:1435290472@qq.com">zq</a>
  * @param img        原图片
  * @param radius     模糊权重
  * @return     模糊后图片
  * @throws IOException
  */
 public static BufferedImage blur(BufferedImage img,int radius) throws IOException{
  int height = img.getHeight();
     int width = img.getWidth();
        int[] values = getPixArray(img, width, height);
        values = doBlur(values, width, height, radius);
     img.setRGB(0, 0, width, height, values, 0, width);
     return img;
 }
 
 /**
  * 
  * <p class="detail">
  * 功能:获取图像像素矩阵
  * </p>
  * @date 2016年4月20日
  * @author <a href="mailto:1435290472@qq.com">zq</a>
  * @param im
  * @param w
  * @param h
  * @return
  */
    private static int[] getPixArray(Image im, int w, int h) { 
        int[] pix = new int[w * h]; 
        PixelGrabber pg = null; 
        try { 
            pg = new PixelGrabber(im, 0, 0, w, h, pix, 0, w); 
            if (pg.grabPixels() != true) 
                try { 
                    throw new java.awt.AWTException("pg error" + pg.status()); 
                } catch (Exception eq) { 
                    eq.printStackTrace(); 
                } 
        } catch (Exception ex) { 
            ex.printStackTrace();
        } 
        return pix; 
    }
    
    /**
     * 
     * <p class="detail">
     * 功能:高斯模糊算法。
     * </p>
     * @date 2016年4月20日
     * @author <a href="mailto:1435290472@qq.com">zq</a>
     * @param pix
     * @param w
     * @param h
     * @param radius
     * @return
     * @throws IOException
     */
    public static int[] doBlur(int[] pix,int w,int h,int radius) throws IOException {
  int wm = w - 1;
  int hm = h - 1;
  int wh = w * h;
  int div = radius + radius + 1;
  int r[] = new int[wh];
  int g[] = new int[wh];
  int b[] = new int[wh];
  int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
  int vmin[] = new int[Math.max(w, h)];
  int divsum = (div + 1) >> 1;
  divsum *= divsum;
  int dv[] = new int[256 * divsum];
  for (i = 0; i < 256 * divsum; i++) {
   dv[i] = (i / divsum);
  }
  yw = yi = 0;
  int[][] stack = new int[div][3];
  int stackpointer;
  int stackstart;
  int[] sir;
  int rbs;
  int r1 = radius + 1;
  int routsum, goutsum, boutsum;
  int rinsum, ginsum, binsum;
  for (y = 0; y < h; y++) {
   rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
   for (i = -radius; i <= radius; i++) {
    p = pix[yi + Math.min(wm, Math.max(i, 0))];
    sir = stack[i + radius];
    sir[0] = (p & 0xff0000) >> 16;
    sir[1] = (p & 0x00ff00) >> 8;
    sir[2] = (p & 0x0000ff);
    rbs = r1 - Math.abs(i);
    rsum += sir[0] * rbs;
    gsum += sir[1] * rbs;
    bsum += sir[2] * rbs;
    if (i > 0) {
     rinsum += sir[0];
     ginsum += sir[1];
     binsum += sir[2];
    } else {
     routsum += sir[0];
     goutsum += sir[1];
     boutsum += sir[2];
    }
   }
   stackpointer = radius;
   for (x = 0; x < w; x++) {
    r[yi] = dv[rsum];
    g[yi] = dv[gsum];
    b[yi] = dv[bsum];
    rsum -= routsum;
    gsum -= goutsum;
    bsum -= boutsum;
    stackstart = stackpointer - radius + div;
    sir = stack[stackstart % div];
    routsum -= sir[0];
    goutsum -= sir[1];
    boutsum -= sir[2];
    if (y == 0) {
     vmin[x] = Math.min(x + radius + 1, wm);
    }
    p = pix[yw + vmin[x]];
    sir[0] = (p & 0xff0000) >> 16;
    sir[1] = (p & 0x00ff00) >> 8;
    sir[2] = (p & 0x0000ff);
    rinsum += sir[0];
    ginsum += sir[1];
    binsum += sir[2];
    rsum += rinsum;
    gsum += ginsum;
    bsum += binsum;
    stackpointer = (stackpointer + 1) % div;
    sir = stack[(stackpointer) % div];
    routsum += sir[0];
    goutsum += sir[1];
    boutsum += sir[2];
    rinsum -= sir[0];
    ginsum -= sir[1];
    binsum -= sir[2];
    yi++;
   }
   yw += w;
  }
  for (x = 0; x < w; x++) {
   rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
   yp = -radius * w;
   for (i = -radius; i <= radius; i++) {
    yi = Math.max(0, yp) + x;
    sir = stack[i + radius];
    sir[0] = r[yi];
    sir[1] = g[yi];
    sir[2] = b[yi];
    rbs = r1 - Math.abs(i);
    rsum += r[yi] * rbs;
    gsum += g[yi] * rbs;
    bsum += b[yi] * rbs;
    if (i > 0) {
     rinsum += sir[0];
     ginsum += sir[1];
     binsum += sir[2];
    } else {
     routsum += sir[0];
     goutsum += sir[1];
     boutsum += sir[2];
    }
    if (i < hm) {
     yp += w;
    }
   }
   yi = x;
   stackpointer = radius;
   for (y = 0; y < h; y++) {
    // Preserve alpha channel: ( 0xff000000 & pix[yi] )
    pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16)
      | (dv[gsum] << 8) | dv[bsum];
    rsum -= routsum;
    gsum -= goutsum;
    bsum -= boutsum;
    stackstart = stackpointer - radius + div;
    sir = stack[stackstart % div];
    routsum -= sir[0];
    goutsum -= sir[1];
    boutsum -= sir[2];
    if (x == 0) {
     vmin[y] = Math.min(y + r1, hm) * w;
    }
    p = x + vmin[y];
    sir[0] = r[p];
    sir[1] = g[p];
    sir[2] = b[p];
    rinsum += sir[0];
    ginsum += sir[1];
    binsum += sir[2];
    rsum += rinsum;
    gsum += ginsum;
    bsum += binsum;
    stackpointer = (stackpointer + 1) % div;
    sir = stack[stackpointer];
    routsum += sir[0];
    goutsum += sir[1];
    boutsum += sir[2];
    rinsum -= sir[0];
    ginsum -= sir[1];
    binsum -= sir[2];
    yi += w;
   }
  }
  return pix;
 }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shi-Tomasi算法(也称为Good-Features-to-Track算法)是一种图像特征检测算法,用于在图像中找到具有良好追踪性的特征点。在图像配准和拼接中,Shi-Tomasi算法可以用来寻找匹配的特征点,从而实现图像的对齐和拼接。 下面是使用Shi-Tomasi算法进行图像配准和拼接的基本步骤: 1. 读取待处理的图片,并将其转换为灰度图像。 2. 对灰度图像进行高斯模糊,以减少噪声干扰。 3. 使用Shi-Tomasi算法检测图像中的角点,得到特征点。 4. 对特征点进行亚像素级别的精确定位。 5. 对两幅图像中的特征点进行匹配,得到相应的匹配点对。 6. 使用RANSAC算法对匹配点对进行筛选,去除误匹配点。 7. 计算图像间的变换矩阵,实现图像的配准。 8. 对配准后的两幅图像进行拼接,得到最终的拼接结果。 在PyCharm中,可以使用OpenCV库来实现Shi-Tomasi算法对图像进行配准和拼接。下面是一个简单的代码示例: ```python import cv2 # 读取两幅待处理的图像 img1 = cv2.imread('image1.jpg', cv2.IMREAD_GRAYSCALE) img2 = cv2.imread('image2.jpg', cv2.IMREAD_GRAYSCALE) # 对图像进行高斯模糊 img1 = cv2.GaussianBlur(img1, (5, 5), 0) img2 = cv2.GaussianBlur(img2, (5, 5), 0) # 使用Shi-Tomasi算法检测特征点 corners1 = cv2.goodFeaturesToTrack(img1, 100, 0.01, 10) corners2 = cv2.goodFeaturesToTrack(img2, 100, 0.01, 10) # 对特征点进行亚像素定位 corners1 = cv2.cornerSubPix(img1, corners1, (5, 5), (-1, -1), criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)) corners2 = cv2.cornerSubPix(img2, corners2, (5, 5), (-1, -1), criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)) # 对特征点进行匹配 matcher = cv2.DescriptorMatcher_create(cv2.DESCRIPTOR_MATCHER_BRUTEFORCE_HAMMING) kps1, descs1 = sift.detectAndCompute(img1, None) kps2, descs2 = sift.detectAndCompute(img2, None) matches = matcher.match(descs1, descs2) # 使用RANSAC算法进行匹配点筛选 src_pts = np.float32([kps1[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2) dst_pts = np.float32([kps2[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2) M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) # 对图像进行配准和拼接 result = cv2.warpPerspective(img1, M, (img1.shape[1] + img2.shape[1], img1.shape[0])) result[0:img2.shape[0], 0:img2.shape[1]] = img2 # 显示结果 cv2.imshow('Result', result) cv2.waitKey() cv2.destroyAllWindows() ``` 需要注意的是,在使用Shi-Tomasi算法进行图像配准和拼接时,需要根据具体情况对算法参数进行调整,以获得更好的结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值