OPENCV图像边缘查找与分割技术在android中使用汇总
来源:互联网 发布:安卓富文本编辑器源码 编辑:程序博客网 时间:2024/06/05 05:04
图像分割技术或者叫抠图技术,是一种根据需要对图像进行截取分离的技术,在一般的图像处理和视频处理中应用十分广泛,是图像查找,图像识别,图像特效的基础。经常被人们使用在相机美颜,自动人脸马赛克,车牌识别,图像查找,人脸查找,人脸识别,机器视觉,AR等领域。
图像分割分有标注和无标注两种情况,一种是自动根据分割,自选阀值,区域自动分割,一种是在给定条件下分割,比如分割人脸,人身体,给定区域分割,前一种由于准确度的问题,应用很少。
主要图像分割方法包括阈值分割,边缘分割(查找边缘),区域分割(种子区域生长法、区域分裂合并法和分水岭法等),图论分割,能量泛函(参数活动轮廓模型,几何活动轮廓模型)等。利用机器学习自动对像素分类也能达到某些分割 目的。
OPENCV封装的分割算法非常多,而且又能根据需要组合使用,以提升分割 精度,这使得用法灵活性大增,掌握的难度比较 大。比较重要的有阀值分割Imgproc.threshold, 边缘分割Imgproc.findContours,也可以使用Roberts 算子、Laplace 算子、Prewitt 算子、Sobel 算子、Rosonfeld算子、Kirsch 算子以及Canny 算子等实现,区域分割HSV亮度, 图论分割GraphCut,GrabCut和Random Walk,还可以根据颜色分割等。有些精度高,耗时长,有些分割粗糙,但速度快,需要根据需要自由组合使用:
import java.util.ArrayList;import java.util.List;import org.opencv.core.Core;import org.opencv.core.CvType;import org.opencv.core.Mat;import org.opencv.core.MatOfPoint;import org.opencv.core.MatOfPoint2f;import org.opencv.core.Point;import org.opencv.core.Rect;import org.opencv.core.Scalar;import org.opencv.core.Size;import org.opencv.imgcodecs.Imgcodecs;import org.opencv.imgproc.Imgproc;public class ImageOpencv {public static void main(String[] args) {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);Mat src = Imgcodecs.imread("E:/work/qqq/a9.jpg"); Imgcodecs.imwrite("E:/work/qqq/hh1.jpg", removeBackground(src)); Mat src2 = Imgcodecs.imread("E:/work/qqq/a3.jpg"); Imgcodecs.imwrite("E:/work/qqq/hh2.jpg", MyThresholdHsv(src2)); Mat src3 = Imgcodecs.imread("E:/work/qqq/e1.jpg"); Imgcodecs.imwrite("E:/work/qqq/hh3.jpg", myGrabCut(src3, new Point(50,0),new Point(300, 250))); Mat src4 = Imgcodecs.imread("E:/work/qqq/dd.jpg"); Imgcodecs.imwrite("E:/work/qqq/hh4.jpg", MyFindLargestRectangle(src4)); Mat src5 = Imgcodecs.imread("E:/work/qqq/dd.jpg"); Imgcodecs.imwrite("E:/work/qqq/hh5.jpg", MyWatershed(src5)); Mat src6 = Imgcodecs.imread("E:/work/qqq/e1.jpg"); Imgcodecs.imwrite("E:/work/qqq/hh6.jpg", MyCanny(src6, 100)); SkinDetection sd= new SkinDetection(Imgcodecs.imread("E:/work/qqq/e1.jpg")); Imgcodecs.imwrite("E:/work/qqq/hh7.jpg",sd.GetSkin()); Mat src7 = Imgcodecs.imread("E:/work/qqq/ee.jpg"); Imgcodecs.imwrite("E:/work/qqq/hh8.jpg", MyFloodFill(src7));}// threshold根据反差去掉深色单色背景public static Mat removeBackground(Mat nat) {Mat m = new Mat();Imgproc.cvtColor(nat, m, Imgproc.COLOR_BGR2GRAY);double threshold = Imgproc.threshold(m, m, 0, 255, Imgproc.THRESH_OTSU);Mat pre = new Mat(nat.size(), CvType.CV_8UC3, new Scalar(0, 0, 0));Mat fin = new Mat(nat.size(), CvType.CV_8UC3, new Scalar(0, 0, 0));for (int i = 0; i < m.rows(); i++) {for (int j = 0; j < m.cols(); j++) {double[] ds = m.get(i, j);double[] data = { ds[0] / 255, ds[0] / 255, ds[0] / 255 };pre.put(i, j, data);}}for (int i = 0; i < pre.rows(); i++) {for (int j = 0; j < pre.cols(); j++) {double[] pre_ds = pre.get(i, j);double[] nat_ds = nat.get(i, j);double[] data = { pre_ds[0] * nat_ds[0], pre_ds[1] * nat_ds[1], pre_ds[2] * nat_ds[2] };fin.put(i, j, data);}}return fin;}// threshold根据亮度去除背景private static Mat MyThresholdHsv(Mat frame) {Mat hsvImg = new Mat();List<Mat> hsvPlanes = new ArrayList<>();Mat thresholdImg = new Mat();// threshold the image with the average hue valuehsvImg.create(frame.size(), CvType.CV_8U);Imgproc.cvtColor(frame, hsvImg, Imgproc.COLOR_BGR2HSV);Core.split(hsvImg, hsvPlanes);// get the average hue value of the imageScalar average = Core.mean(hsvPlanes.get(0));double threshValue = average.val[0];Imgproc.threshold(hsvPlanes.get(0), thresholdImg, threshValue, 179.0, Imgproc.THRESH_BINARY_INV);Imgproc.blur(thresholdImg, thresholdImg, new Size(15, 15));// dilate to fill gaps, erode to smooth edgesImgproc.dilate(thresholdImg, thresholdImg, new Mat(), new Point(-1, -1), 1);Imgproc.erode(thresholdImg, thresholdImg, new Mat(), new Point(-1, -1), 3);Imgproc.threshold(thresholdImg, thresholdImg, threshValue, 179.0, Imgproc.THRESH_BINARY);// create the new imageMat foreground = new Mat(frame.size(), CvType.CV_8UC3, new Scalar(0, 0, 0));thresholdImg.convertTo(thresholdImg, CvType.CV_8U);frame.copyTo(foreground, thresholdImg);return foreground;} //grabCut分割技术public static Mat myGrabCut(Mat in, Point tl, Point br) {Mat mask = new Mat();Mat image = in;mask.create(image.size(), CvType.CV_8UC1);mask.setTo(new Scalar(0));Mat bgdModel = new Mat();// Mat.eye(1, 13 * 5, CvType.CV_64FC1);Mat fgdModel = new Mat();// Mat.eye(1, 13 * 5, CvType.CV_64FC1);Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(3));Rect rectangle = new Rect(tl, br);Imgproc.grabCut(image, mask, rectangle, bgdModel, fgdModel, 3, Imgproc.GC_INIT_WITH_RECT);Core.compare(mask, source, mask, Core.CMP_EQ);Mat foreground = new Mat(image.size(), CvType.CV_8UC1, new Scalar(0, 0, 0));image.copyTo(foreground, mask);return foreground;}//findContours分割技术private static Mat MyFindLargestRectangle(Mat original_image) {Mat imgSource = original_image;Imgproc.cvtColor(imgSource, imgSource, Imgproc.COLOR_BGR2GRAY);Imgproc.Canny(imgSource, imgSource, 50, 50);Imgproc.GaussianBlur(imgSource, imgSource, new Size(5, 5), 5);List<MatOfPoint> contours = new ArrayList<MatOfPoint>();Imgproc.findContours(imgSource, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);double maxArea = 0;int maxAreaIdx = -1;MatOfPoint largest_contour = contours.get(0); MatOfPoint2f approxCurve = new MatOfPoint2f();for (int idx = 0; idx < contours.size(); idx++) {MatOfPoint temp_contour = contours.get(idx);double contourarea = Imgproc.contourArea(temp_contour);if (contourarea - maxArea > 1) {maxArea = contourarea;largest_contour = temp_contour;maxAreaIdx = idx;MatOfPoint2f new_mat = new MatOfPoint2f(temp_contour.toArray());int contourSize = (int) temp_contour.total();Imgproc.approxPolyDP(new_mat, approxCurve, contourSize * 0.05, true);}}Imgproc.drawContours(imgSource, contours, -1, new Scalar(255, 0, 0), 1);Imgproc.fillConvexPoly(imgSource, largest_contour, new Scalar(255, 255, 255));Imgproc.drawContours(imgSource, contours, maxAreaIdx, new Scalar(0, 0, 255), 3);return imgSource;}//watershed分水岭分割技术 public static Mat MyWatershed(Mat img) { Mat threeChannel = new Mat(); Imgproc.cvtColor(img, threeChannel, Imgproc.COLOR_BGR2GRAY); //Imgproc.threshold(threeChannel, threeChannel, 200, 255, Imgproc.THRESH_BINARY); Imgproc.threshold(threeChannel, threeChannel, 0, 255, Imgproc.THRESH_OTSU); Mat fg = new Mat(img.size(),CvType.CV_8U); Imgproc.erode(threeChannel,fg,new Mat()); Mat bg = new Mat(img.size(),CvType.CV_8U); Imgproc.dilate(threeChannel,bg,new Mat()); Imgproc.threshold(bg,bg,1, 128,Imgproc.THRESH_BINARY_INV); Mat markers = new Mat(img.size(),CvType.CV_8U, new Scalar(0)); Core.add(fg, bg, markers); Mat result=new Mat(); markers.convertTo(result, CvType.CV_32SC1); Imgproc.watershed(img, result); result.convertTo(result,CvType.CV_8U); return result; } //Canny分割技术 public static Mat MyCanny(Mat img, int threshold) { Imgproc.cvtColor(img, img, Imgproc.COLOR_BGR2GRAY); Imgproc.Canny(img, img, threshold, threshold * 3, 3, true); return img; } //漫水填充 public static Mat MyFloodFill(Mat img) { Rect ccomp = new Rect(); Mat mask = new Mat(); Imgproc.floodFill(img, mask, new Point(50,20), new Scalar(0, 0,0), ccomp,new Scalar(10, 10, 10), new Scalar(10, 10, 10), 0); return img; } }
上图:
removeBackground,较深单色背景时
MyThresholdHsv,较浅亮色背景
myGrabCut去除复杂背景
查找边缘轮廓,提取mask用于分割
MyWatershed
MyCanny和基于肤色分割
参考 :
http://blog.csdn.net/zouxy09/article/details/8532106
http://blog.csdn.net/vast_sea/article/details/8196507
http://blog.csdn.net/bless2015/article/details/52805875
http://www.07net01.com/2016/04/1458778.html
http://blog.csdn.net/dcrmg/article/details/52498440
http://blog.csdn.net/liang_dun/article/details/45198911
- OPENCV图像边缘查找与分割技术在android中使用汇总
- 边缘检测与图像分割
- 图像分割与边缘检测
- 图像分割技术之图像边缘检测
- Opencv 图像分割: 阈值化分割 区域分割 边缘分割
- android studio 使用 jni 编译 opencv 完整实例 之 图像边缘检测!从此在andrid中自由使用 图像匹配、识别、检测
- android studio 使用 jni 编译 opencv 完整实例 之 图像边缘检测!从此在andrid中自由使用 图像匹配、识别、检测
- OpenCV:查找图像边缘并画出直线
- U-net使用, 图像分割(边缘检测)
- U-net使用, 图像分割(边缘检测)
- U-net使用, 图像分割(边缘检测)
- U-net使用, 图像分割(边缘检测)
- OpenCV高斯差分技术实现图像边缘检测
- opencv图像边缘检测使用,先做平滑处理在进行边缘检测
- 在Android中使用JNI调用Opencv本地代码 配置方式 边缘检测 范例代码
- OpenCV使用Canny边缘检测器实现图像边缘检测
- 利用OpenCV提取图像的边缘,并将检测的边缘重新保存在一个新的文件中
- 使用OpenCV在MFC中显示图像
- weui-tabbar老是在顶部 如何让 height:100%; 起作用
- 剑指offer面试题2:实现Singleton模式(Java版)
- 区间LCM
- spring第一天
- 数据库索引的实现原理
- OPENCV图像边缘查找与分割技术在android中使用汇总
- hdu4614 Vases and Flowers (线段树)
- How To Install Ruby with rbenv on Cent OS 7.2
- ubuntu systemctl generated and enabled
- [kaggle数据] 泰坦尼克号生存预测分析
- Oracle存储过程基本语法及基础教程
- 计算机系大学生、程序员怎么在空余时间赚钱
- LeetCode:595 Big Countions
- C#--抽象工厂设计模式原理