Photo提供了降噪Denosing、动态成像HDR、图片拼接等api,类似于Photoshop。
图片填充:
去色演示:


降噪效果演示:


两张噪点图片:
lena1

lena2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; import javax.swing.ButtonGroup; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JRadioButton; import javax.swing.JSlider; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.photo.Photo; public class InPaint extends JFrame { private final JLabel imageView; private Mat srcMat; public InPaint() { srcMat = Imgcodecs.imread("./lena_dirty.jpg"); JLabel inpaintRadiusLabel = new JLabel("半径:" + 0); inpaintRadiusLabel.setBounds(15, 10, 60, 15); JSlider inpaintRadiusBar = new JSlider(0, 50); inpaintRadiusBar.setValue(0); inpaintRadiusBar.setBounds(80, 5, 120, 25); JRadioButton nsBtn = new JRadioButton("INPAINT_NS"); nsBtn.setSelected(true); nsBtn.setBounds(230, 10, 120, 15); JRadioButton teleaBtn = new JRadioButton("INPAINT_TELEA"); teleaBtn.setBounds(350, 10, 120, 15); ButtonGroup group = new ButtonGroup(); group.add(nsBtn); group.add(teleaBtn); inpaintRadiusBar.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { double value = inpaintRadiusBar.getValue(); inpaintRadiusLabel.setText("半径:" + value); int type = nsBtn.isSelected() ? 1 : 0; inpaint(value, type); } }); nsBtn.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { double value = inpaintRadiusBar.getValue(); inpaintRadiusLabel.setText("半径:" + value); int type = nsBtn.isSelected() ? 1 : 0; inpaint(value, type); } }); teleaBtn.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent e) { double value = inpaintRadiusBar.getValue(); inpaintRadiusLabel.setText("半径:" + value); int type = nsBtn.isSelected() ? 1 : 0; inpaint(value, type); } }); imageView = new JLabel(); imageView.setBounds(5, 5, 512, 512); this.setTitle("图片处理"); this.setSize(550, 580); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.getContentPane().setLayout(null); this.getContentPane().add(inpaintRadiusLabel); this.getContentPane().add(inpaintRadiusBar); this.getContentPane().add(nsBtn); this.getContentPane().add(teleaBtn); this.getContentPane().add(imageView); setIcon(srcMat); } /** * 区域填充 * * @param inpaintRadius 数值越大,修复区域越模糊-过渡越好 * @param flags 本例 INPAINT_TELEA 慢于 INPAINT_NS */ private void inpaint(double inpaintRadius, int flags) { Mat dstMat = new Mat(srcMat.size(), CvType.CV_8UC3); Mat inpaintMaskMat = Imgcodecs.imread("./lena_dirtymask.jpg", CvType.CV_8UC1); // 模拟手动选择的要修复的区域 if (1 == flags) { Photo.inpaint(srcMat, inpaintMaskMat, dstMat, inpaintRadius, Photo.INPAINT_NS); // 边缘线算法 } else { Photo.inpaint(srcMat, inpaintMaskMat, dstMat, inpaintRadius, Photo.INPAINT_TELEA); // 临近像素算法 } setIcon(dstMat); } // 去色 private void decolor() { srcMat = Imgcodecs.imread("./lena.jpg"); Mat grayscaleMat = new Mat(); // 灰阶图,8位单通道 Mat colorBoostMat = new Mat(); // 彩图,8位三通道 Photo.decolor(srcMat, grayscaleMat, colorBoostMat); setIcon(grayscaleMat); setIcon(colorBoostMat); } // 降噪-去除杂点。图片整体上有种柔化的感觉 private void fastNlMeansDenoising(){ Mat dstMat = new Mat(); // 方法1。可用于单通道、3通道图 // fastNlMeansDenoising(Mat src, Mat& dst, float h = 3, int templateWindowSize = 7, int searchWindowSize = 21) Photo.fastNlMeansDenoising(srcMat, dstMat); // 方法2。按照索引去除杂点。可用于单通道、3通道图 Mat im1 = Imgcodecs.imread("./lena1.jpg",Imgcodecs.CV_LOAD_IMAGE_COLOR); Mat im2 = Imgcodecs.imread("./lena2.jpg",Imgcodecs.CV_LOAD_IMAGE_COLOR); List<Mat> srcImgs=new ArrayList<>(); srcImgs.add(im1); // 杂点图片 srcImgs.add(im2); // 杂点图片 srcImgs.add(srcMat); // fastNlMeansDenoisingMulti(vector_Mat srcImgs, Mat& dst, int imgToDenoiseIndex, int temporalWindowSize, float h = 3, int templateWindowSize = 7, int searchWindowSize = 21) // imgToDenoiseIndex 指srcImgs中"杂点的索引"图片的索引。 // temporalWindowSize 要去除的杂点周围的像素数量,须奇数。 Photo.fastNlMeansDenoisingMulti(srcImgs, dstMat, 2, 1); // 方法3。可用于3通道图 // fastNlMeansDenoisingColored(Mat src, Mat& dst, float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21) Photo.fastNlMeansDenoisingColored(srcMat, dstMat); // 方法4 // fastNlMeansDenoisingColoredMulti(vector_Mat srcImgs, Mat& dst, int imgToDenoiseIndex, int temporalWindowSize, float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21) Photo.fastNlMeansDenoisingColoredMulti(srcImgs, dstMat, 2, 1); // 方法5 Mat img = Imgcodecs.imread("./lena.jpg",Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE); // 转灰度图 CV_LOAD_IMAGE_GRAYSCALE :gray = 0.299 * r + 0.587 * g + 0.114 * b ,小数点部分四舍五入为整数 Mat img1 = Imgcodecs.imread("./lena1.jpg",Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE); Mat img2 = Imgcodecs.imread("./lena2.jpg",Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE); List<Mat> srcList=new ArrayList<Mat>(); srcList.add(img); // srcList.add(img1); // srcList.add(img2); // denoise_TVL1(vector_Mat observations, Mat result, double lambda = 1.0, int niters = 30) // lambda 数值越小,图像越模糊-柔化 // niters 运算次数 Photo.denoise_TVL1(srcList, dstMat, 10, 10); setIcon(dstMat); } private void setIcon(Mat mat) { BufferedImage image = CVUtil.matToBufferedImage(mat); // CVUtil 见 http://www.gaohaiyan.com/3229.html imageView.setIcon(new ImageIcon(image)); } } |
- end
声明
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/3551.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设