OPENCV图像边缘查找与分割技术在android中使用汇总

您所在的位置:网站首页 opencv分析轮廓,寻找边界线 OPENCV图像边缘查找与分割技术在android中使用汇总

OPENCV图像边缘查找与分割技术在android中使用汇总

2022-06-10 22:27| 来源: 网络整理| 查看: 265

图像分割技术或者叫抠图技术,是一种根据需要对图像进行截取分离的技术,在一般的图像处理和视频处理中应用十分广泛,是图像查找,图像识别,图像特效的基础。经常被人们使用在相机美颜,自动人脸马赛克,车牌识别,图像查找,人脸查找,人脸识别,机器视觉,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()); } // 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 hsvPlanes = new ArrayList(); Mat thresholdImg = new Mat(); // threshold the image with the average hue value hsvImg.create(frame.size(), CvType.CV_8U); Imgproc.cvtColor(frame, hsvImg, Imgproc.COLOR_BGR2HSV); Core.split(hsvImg, hsvPlanes); // get the average hue value of the image Scalar 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 edges Imgproc.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 image Mat 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 contours = new ArrayList(); 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; } } 上图:

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3