Imgproc.boundingRect
Mat.submat
Imgproc.line
Imgproc.polylines
Imgproc.fillPoly
Core.bitwise_and
先画出不规则图形ploy,
计算ploy所在的最小矩形rect,
从源图像截取rect区域的图像roi,
根据ploy得到一个对应roi的roi_ploy,
通过roi_ploy为roi创建一个mask,
用mask对roi计算得到不规则的图像。
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 |
import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.MatOfPoint; import org.opencv.core.Point; import org.opencv.core.Rect; import org.opencv.core.Scalar; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; public class RegionOfInterest extends JFrame { public List<Point> polyPointList = new ArrayList<Point>(); private List<Integer> pointX = new ArrayList<Integer>(); private List<Integer> pointY = new ArrayList<Integer>(); private final JLabel imageView; private final JLabel roiImgView; private Mat srcMat; private boolean isClose = false; public RegionOfInterest() { srcMat = Imgcodecs.imread("./lena.jpg"); JButton colseBtn = new JButton("闭合"); colseBtn.setBounds(15, 10, 70, 25); colseBtn.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { isClose = true; drawPolyLines(null); } }); JButton copyBtn = new JButton("拷贝"); copyBtn.setBounds(100, 10, 100, 25); copyBtn.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { Mat roi = getRoiMat(); BufferedImage newImage = CVUtil.matToBufferedImage(roi); roiImgView.setIcon(new ImageIcon(newImage)); polyPointList.clear(); } }); imageView = new JLabel(); imageView.setBounds(15, 40, 512, 512); imageView.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { Point point = new Point(e.getX(), e.getY()); drawPolyLines(point); } }); roiImgView = new JLabel(); roiImgView.setBounds(540, 40, 512, 512); this.setTitle("区域图像选择"); this.setSize(1100, 580); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.getContentPane().setLayout(null); this.getContentPane().add(colseBtn); this.getContentPane().add(copyBtn); this.getContentPane().add(imageView); this.getContentPane().add(roiImgView); setIcon(srcMat); } public void drawPolyLines(Point point) { if (null == point) { isClose = true; } else { polyPointList.add(point); } Mat canvas = srcMat.clone(); Scalar color = new Scalar(256, 64, 128); if (polyPointList.size() < 2) { Point p = polyPointList.get(0); Imgproc.line(canvas, p, p, color, 8); } else { MatOfPoint mp = new MatOfPoint(); mp.fromList(polyPointList); List<MatOfPoint> pts = new ArrayList<>(); pts.add(mp); Imgproc.polylines(canvas, pts, isClose, color, 8); if (isClose) { isClose = false; } } setIcon(canvas); } public Mat getRoiMat() { Rect rect; // 全部的点所在的最小矩形区域 if (1 == 0) { // 方法1 List<Integer> pointX = new ArrayList<>(); List<Integer> pointY = new ArrayList<>(); for (int i = 0; i < polyPointList.size(); i++) { Point point = polyPointList.get(i); pointX.add((int) point.x); pointY.add((int) point.y); } int minX, minY, maxX, maxY; minX = Collections.min(pointX); // 不规则矩形最左边的点x minY = Collections.min(pointY); // 不规则矩形最左边的点y maxX = Collections.max(pointX); // 不规则矩形最右边的点x maxY = Collections.max(pointY); // 不规则矩形最右边的点y rect = new Rect(new Point(minX, minY), new Point(maxX, maxY)); } else { // 方法2 MatOfPoint mp = new MatOfPoint(); mp.fromList(polyPointList); rect = Imgproc.boundingRect(mp); } Mat roiMat = srcMat.submat(rect); // 截取这块矩形图像。这里是矩形的。 List<Point> roiPoints = new ArrayList<>(); // 组织一批新的点 for (int i = 0; i < polyPointList.size(); i++) { Point point = polyPointList.get(i); double x = point.x - rect.x; double y = point.y - rect.y; roiPoints.add(new Point(x, y)); // 点位置匹配到roiMat图像内,即假想的roiMat图像上的不规则图形 } MatOfPoint mp = new MatOfPoint(); mp.fromList(roiPoints); List<MatOfPoint> pts = new ArrayList<>(); pts.add(mp); Mat img = new Mat(roiMat.size(), CvType.CV_8UC1, new Scalar(0)); // 创建一个黑色的副本图,和roiMat等大 Imgproc.fillPoly(img, pts, new Scalar(255, 255, 255)); // 在副本上,按照不规则图形填充白色,不在不规则图形内的即副本的黑色 Mat dst = new Mat(); // 新的图像 // src1-源图或颜色, src2-源图或颜色, dst-输出图, mask-遮罩图 Core.bitwise_and(roiMat, roiMat, dst, img); // 对灰度图或彩色图像素值进行二进制“与”操作,1&1=1,1&0=0,0&1=0,0&0=0。 return dst; } private void setIcon(Mat mat) { BufferedImage image = CVUtil.matToBufferedImage(mat); // CVUtil 见 http://www.gaohaiyan.com/3229.html imageView.setIcon(new ImageIcon(image)); } } |
代码中,144-147行,鼠标划出区域的不规则图形“dst”,还可以合并到源图srcMat或其它图片,类似Photoshop的图层合并。
1.先根据dst大小,在srcMat上确定一个位置 rect=new Rect(point(左上), point(右下)); ,
2.然后 posMat = srcMat.submat(rect); ,
3.将上面的图合并到下面的图,dst.copyTo(posMat, dst); 第2个参数为mask,仍使用dst则处理后黑色区域透明。
此时的srcMat就是新图了。
- end
声明
本文由崔维友 威格灵 cuiweiyou vigiles cuiweiyou 原创,转载请注明出处:http://www.gaohaiyan.com/3312.html
承接App定制、企业web站点、办公系统软件 设计开发,外包项目,毕设