文档章节

OPENCV 使用系列二 grabcut 的使用(简单但有用的图像分割)

zhuyuping
 zhuyuping
发布于 2016/04/13 14:44
字数 1857
阅读 1846
收藏 0
点赞 1
评论 0

看到 博客的文章,里面 opencv 很早以前发的东西,发现 怎么看 都不完整 看起来很别扭,于是今天我加上一篇 教程 关于 opencv 的grabcut简单的图像分割算法 ,这个在很多 图像爬虫中 然后需要对图像分割 处理 符合我们需要的图片时候 很有用 ,下面 我们来测试测试。

这个opencv 后续 我会推出opencv怎么使用opencv自带的ML机器学习算法,在手机端,有时候用不了那么多机器学习库,用opencv 也是一个很好的方式,使用opencv 来做移动端的一些简单的机器学习

这里我就简单说一下 简单的方式 怎么做到的吧。很简单 。大家如果 有下面类似的 从图片抓取的 分割出图像出来的需求 ,可以直接使用这种方式。

下面是 需要被处理的图片,我们有个场景,抓取了好多淘宝图片 ,但是我们只需要单品图片,过滤掉背景 ,我们只需要那最重要的那部分图片保存起来,这样我们app 上展示 就是我们的商品图片了

        

   下面 第一部分 是grabcut算法 的核心 代码 

   过程 分别是 首先转为灰度 color2gray 然后使用ostu算法得到阈值 ,然后高斯模糊 使得减少噪音,然后查找轮廓contours 最后 从轮廓中找到最大的轮廓 。这里 有模特的图片 所以 加了一部分皮肤侦测 

  public static BufferedImage grabcut(Mat  src){
		Mat thr = new Mat();
		Imgproc.cvtColor(src, thr, Imgproc.COLOR_BGR2GRAY);
		// Imgproc.THRESH_BINARY + Imgproc.THRESH_OTSU
		 Imgproc.GaussianBlur(thr, thr, new Size(3, 3), 0);
		// http://docs.opencv.org/master/d7/d4d/tutorial_py_thresholding.html#gsc.tab=0
		Imgproc.threshold(thr, thr, 0, 255, Imgproc.THRESH_BINARY
				+ Imgproc.THRESH_OTSU); // Threshold the gray
		// Imgproc.adaptiveThreshold(imgGray, imgThreshold, 255,
		// Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 11, 2);
		List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); // Vector for
		// adaptiveThreshold(gray, result, 255, ADAPTIVE_THRESH_MEAN_C,
		// THRESH_BINARY, 15, 40);
		// double mean = Core.mean(image).val[0];
		// Imgproc.GaussianBlur(imageMat, imageMat, new Size(3, 3), 0);
		// Imgproc.threshold(imageMat, imageMat, 0, 255, Imgproc.THRESH_OTSU);
		// cvSmooth(imageMat, imageMat, CV_MEDIAN, new Size(3, 3), 0);
		// Imgproc.adaptiveThreshold(imageMat, imageMat, 255,
		// Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 5, 4);
		Mat h = new Mat();
		double largest_area = 0;
		int largest_contour_index = 0;
		Rect bounding_rect = new Rect();
		Imgproc.findContours(thr, contours, h, Imgproc.RETR_CCOMP,
				Imgproc.CHAIN_APPROX_SIMPLE); // Find the contours in the image
		for (int i = 0; i < contours.size(); i++) // iterate through each
		{
			double a = Imgproc.contourArea(contours.get(i), false); // Find the
			if (a > largest_area) {
				largest_area = a;
				largest_contour_index = i; // Store the index of largest contour
				bounding_rect = Imgproc.boundingRect(contours.get(i)); // Find
			}

		}
		int width=bounding_rect.width;
		int height=bounding_rect.height;
		if(largest_area==0||width<160||height<160){
			//没有轮廓不做处理
			return OpenCVUtil.matToBufferedImage(src);
		}else{
		
		int x1=bounding_rect.x;
		int y1=bounding_rect.y;
		int x2=x1+width;
		int y2=y1+height;
		Point tl=new Point(x1, y1);
		Point br=new Point(x2, y2);
		return grabcut(src,tl,br);   
		}    
    	
    }
    
    public static BufferedImage grabcut(Mat img,Point tl,Point br){
       Mat background = new Mat(img.size(), CvType.CV_8UC3,
               new Scalar(255, 255, 255));
       Mat firstMask = new Mat();
       Mat bgModel = new Mat();
       Mat fgModel = new Mat();
       Mat mask;
       Mat source = new Mat(1, 1, CvType.CV_8U, new Scalar(Imgproc.GC_PR_FGD));
       Mat dst = new Mat();
       Rect rect = new Rect(tl, br);
       Imgproc.grabCut(img, firstMask, rect, bgModel, fgModel,
               5, Imgproc.GC_INIT_WITH_RECT);
       Core.compare(firstMask, source, firstMask, Core.CMP_EQ);
       Mat foreground = new Mat(img.size(), CvType.CV_8UC3,
               new Scalar(255, 255, 255));
       img.copyTo(foreground, firstMask);
       Scalar color = new Scalar(255, 0, 0, 255);
       Core.rectangle(img, tl, br, color);
       Mat tmp = new Mat();
       Imgproc.resize(background, tmp, img.size());
       background = tmp;
       mask = new Mat(foreground.size(), CvType.CV_8UC1,
               new Scalar(255, 255, 255));
       Imgproc.cvtColor(foreground, mask, Imgproc.COLOR_BGR2GRAY);
       Imgproc.threshold(mask, mask, 254, 255, Imgproc.THRESH_BINARY_INV);
       Mat vals = new Mat(1, 1, CvType.CV_8UC3, new Scalar(0.0));
       background.copyTo(dst);
       background.setTo(vals, mask);
       Core.add(background, foreground, dst, mask);
       firstMask.release();
       source.release();
       bgModel.release();
       fgModel.release();
       vals.release();
       //Highgui.imwrite("/root/grabcut.jpg", dst);
       return OpenCVUtil.matToBufferedImage(dst);
	}

 

下面看看 我怎么写的

    

public class SkinDetectTest2 {

	
	
	static {
		 
		
		 System.loadLibrary(org.opencv.core.Core.NATIVE_LIBRARY_NAME);
	}
	private static List<File> getFiles(String fileName) {
	    File file=new File(fileName);
	    return Lists.newArrayList(file.listFiles(new FilenameFilter() {
			
			@Override
			public boolean accept(File dir, String name) {
				if(name.endsWith(".jpg")||name.endsWith(".png")){ 
					return true;
				}
				
				return false;
			}
		}));
	    
	}
	
	  public static void main(String[] args) {
		
		  List<File> files=getFiles("c:/mnt");
			for (File file : files) {
				  Mat image=Highgui.imread(file.getAbsolutePath());
				  System.out.println(image.width()+"*****************"+image.height());
				  //YCrCbSkinDetector cbSkinDetector=new YCrCbSkinDetector();
				  SkinDetection detection=new SkinDetection(image);
				  //Mat result=cbSkinDetector.detectSkin(image, cbSkinDetector.ycrcbMin, cbSkinDetector.ycrcbMax);
				  Mat skin=detection.GetSkin();//960
				  Highgui.imwrite("c:/mnt/result/"+file.getName()+"skin1.jpg", skin);
				  System.out.println(skin.width()+"======="+skin.height());
				  Mat thr = new Mat();
					Imgproc.cvtColor(image, thr, Imgproc.COLOR_BGR2GRAY);
					// Imgproc.THRESH_BINARY + Imgproc.THRESH_OTSU
					 Imgproc.GaussianBlur(thr, thr, new Size(3, 3), 0);
					// http://docs.opencv.org/master/d7/d4d/tutorial_py_thresholding.html#gsc.tab=0
					 double testmean = Core.mean(skin).val[0];//1
					Imgproc.threshold(thr, thr, testmean, 255, Imgproc.THRESH_OTSU );//Imgproc.THRESH_OTSU); // Threshold the gray// Imgproc.THRESH_BINARY
					  //+ Imgproc.THRESH_OTSU
					// Imgproc.adaptiveThreshold(imgGray, imgThreshold, 255,
					// Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 11, 2);
					List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); // Vector for
					// adaptiveThreshold(gray, result, 255, ADAPTIVE_THRESH_MEAN_C,
					// THRESH_BINARY, 15, 40);
					// double mean = Core.mean(image).val[0];
					
					// Imgproc.threshold(imageMat, imageMat, 0, 255, Imgproc.THRESH_OTSU);
					// cvSmooth(imageMat, imageMat, CV_MEDIAN, new Size(3, 3), 0);
					// Imgproc.adaptiveThreshold(imageMat, imageMat, 255,
					// Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 5, 4);
					Mat h = new Mat();
					double largest_area = 0;
					int largest_contour_index = 0;
					Rect maxbounding_rect = new Rect();
					Imgproc.findContours(thr, contours, h, Imgproc.RETR_CCOMP,
							Imgproc.CHAIN_APPROX_SIMPLE); // Find the contours in the image
					List<Rect> rects=Lists.newArrayList();
					for (int i = 0; i < contours.size(); i++) // iterate through each
					{
						
		               
						Rect bounding_rect = Imgproc.boundingRect(contours.get(i)); // Find
						int width=bounding_rect.width;
						int height=bounding_rect.height;
						int x=bounding_rect.x;
						int y=bounding_rect.y;
		                if(contours.size()>1&&(x<10||y<10)){
							continue;
						}
						double a = Imgproc.contourArea(contours.get(i), false); // Find the
						if (a > largest_area) {
							largest_area = a;
							largest_contour_index = i; // Store the index of largest contour
							maxbounding_rect = Imgproc.boundingRect(contours.get(i)); // Find
						}
						if(width>150&&height>150){
					    double wh= (width/(height*1.0));
						//if(wh>1.7) continue;//过滤掉长宽高相差很远的
						//System.out.println(width+"=========="+height+"============="+bounding_rect.x+"==================="+bounding_rect.y);
						Point tl=bounding_rect.tl();
						Point bl=bounding_rect.br();
						System.out.println(tl+"============"+bl+"==========="+width+"=============="+height+"################"+wh);
						Core.rectangle(image, new Point(bounding_rect.x, bounding_rect.y), new Point(bounding_rect.x + bounding_rect.width, bounding_rect.y + bounding_rect.height),
						        new Scalar(0, 255, 0));
						rects.add(bounding_rect);
						}
					}
					System.out.println(maxbounding_rect.width/(maxbounding_rect.height*1.0)+"####################"+maxbounding_rect.tl()+"---------------"+maxbounding_rect.br()+"-----------------"+maxbounding_rect.width+"------------"+maxbounding_rect.height);
		            double maxwh=maxbounding_rect.width/(maxbounding_rect.height*1.0);
		            
		            
					//			Core.rectangle(skin, new Point(bounding_rect.x, bounding_rect.y), new Point(bounding_rect.x + bounding_rect.width, bounding_rect.y + bounding_rect.height),
//					        new Scalar(0, 255, 0));
				  // Mat newsrc=ImageUtils.grabcutMat(image,maxbounding_rect);
//		          for (Rect rect : rects) {
//		        	    int width=rect.width;
//						int height=rect.height;
//						int x=rect.x;
//						int y=rect.y;
//						if(rects.size()>1&&x<10&&y<10) continue;
//						
//				  }
				  Highgui.imwrite("c:/mnt/result/"+file.getName()+"roi.jpg", image);
				  YCrCbSkinDetector cbSkinDetector=new YCrCbSkinDetector();
				  Mat result=cbSkinDetector.detectSkin(skin, cbSkinDetector.ycrcbMin, cbSkinDetector.ycrcbMax);
				  double mean = Core.mean(result).val[0];//1
				  System.out.println("=============="+mean);//mean 为0 或者 接近<2 没有脸
				  Highgui.imwrite("c:/mnt/result/"+file.getName()+"skinresult"+mean+".jpg", result);
				  //0.6 1 1 2
			}
	
		  
//		  @Override
//		    public Image filter(Image input) {
//		        Mat outputMat = new Mat();
//		        Mat inputMat = input.getData();
//		        Mat inputMatGreyscale = new Mat();
//		        Imgproc.cvtColor(inputMat, inputMatGreyscale, Imgproc.COLOR_RGB2GRAY);
//		        fastNlMeansDenoising(inputMatGreyscale, outputMat, 5, 13, 21);
//		        input.release();
//		        inputMatGreyscale.release();
//		        Image output = new Image(outputMat);
//		        return output;
//		    }

		  
		  
		  
	}

  

import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

//program adapted from http://bytefish.de/blog/opencv/skin_color_thresholding/
public class SkinDetection {

	Mat inputImage;
	
	public SkinDetection(Mat image){
		this.inputImage = image;
	}
	
	
	public boolean ruleRGB(int R,int G, int B){
		boolean value1 = (R>95) && (G>40) && (B>20) && ((Math.max(R,Math.max(G,B)) - Math.min(R, Math.min(G,B)))>15) && (Math.abs(R-G)>15) && (R>G) && (R>B);
		boolean value2 =(R>220) && (G>210) && (B>170) && (Math.abs(R-G)<=15) && (R>B) && (G>B);
		return (value1||value2);
	}
	
	public boolean ruleHSV(int H, int S, int V){
		return (H<25) || (H> 230);
	}
	
	public boolean ruleYCrCb(int Y,int Cr, int Cb){
		 	boolean value1 = Cr <= 1.5862*Cb+20;
		    boolean value2 = Cr >= 0.3448*Cb+76.2069;
		    boolean value3 = Cr >= -4.5652*Cb+234.5652;
		    boolean value4 = Cr <= -1.15*Cb+301.75;
		    boolean value5 = Cr <= -2.2857*Cb+432.85;
		    return value1 && value2 && value3 && value4 && value5;
	}
	
	public Mat GetSkin(){
		//Important to load this line, it calls in the Native Library
		 System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		 
		Mat outputImage = inputImage.clone();
		
		
		Mat srcYCrCb = inputImage.clone() , srcHSV = inputImage.clone();
	    
		//Convert the image into YCrCb and HSV ranges.
		Imgproc.cvtColor(inputImage, srcYCrCb, Imgproc.COLOR_BGR2YCrCb);
		inputImage.convertTo(srcHSV,inputImage.type());
		Imgproc.cvtColor(srcHSV, srcHSV, Imgproc.COLOR_BGR2HSV);
		//Normalize the values for HSV
		Core.normalize(srcHSV,srcHSV,0.0,255.0,Core.NORM_MINMAX,inputImage.type());
		double zero[] = new double[]{0,0,0}; 
		
		for(int row =0; row< inputImage.rows();row++){
			for(int col=0; col<inputImage.cols();col++){
				//fetch values in the respective color space
				 double pixel[] = inputImage.get(row, col);
				 double pixelYCrCb[] = srcYCrCb.get(row, col);
				 double pixelHSV[] = srcHSV.get(row, col);
				 
				 
				 int B = (int)pixel[0];
				 int G = (int) pixel[1];
				 int R = (int) pixel[2];
				 boolean resultsRGB = ruleRGB(R, G, B);
				 
				 int Y = (int) pixelYCrCb[0];
				 int Cr= (int) pixelYCrCb[1];
				 int Cb= (int) pixelYCrCb[2];
				 boolean resultsYCrCb = ruleYCrCb(Y, Cr, Cb);
				 
				 int H = (int)pixelHSV[0];
				 int S = (int)pixelHSV[1];
				 int V = (int)pixelHSV[2];
				 boolean resultsHSV = ruleHSV(H, S, V);
				 
				 if(!(resultsRGB && resultsYCrCb && resultsHSV  )){ 
					 outputImage.put(row,col,zero);
				 }
					 
			}
		}
		
		
		return outputImage;
	}
	
}


下面 看看运行结果 

   

   这里 是打印的轮廓 X  Y坐标位置 大小 以及 长宽比 ,这个可以用来调节排除过滤 一些不符合条件的图片 

   下面看看 输出结果

   这在之前 ,指出一段代码 ,这段代码 是画一个框 颜色是sclaar 0 255 0 也就是 是绿色,正常环境 把它换成subimage截取图像就可以了 ,因为宽高 x y 起始位置我们都知道 。

Core.rectangle(image, new Point(bounding_rect.x, bounding_rect.y), new Point(bounding_rect.x + bounding_rect.width, bounding_rect.y + bounding_rect.height),
						        new Scalar(0, 255, 0));

 下面 贴出结果 注意 看我们绿色 画框框的地方  Core.rectangle 

  


© 著作权归作者所有

共有 人打赏支持
zhuyuping
粉丝 303
博文 35
码字总数 51047
作品 0
徐汇
程序员
OpenCV学习笔记-图像分割之GrabCut

点击打开链接,点击打开链接 grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode=None) GCDPRBGD和GCDPRFGD bdgModel,fgdModel: 算法内部使用的数组,只需要创建两个大小为(1,...

qq_36387683 ⋅ 05/30 ⋅ 0

基于OpenCV和Python的文件操作——捕获摄像头的帧,在窗口显示图像,在窗口显示摄像头帧和视频文件的读/写

0 写在前面 这篇博客主要参考资料为《OpenCV 3计算机视觉Python语言实现》(Learning OpenCV 3 Computer Vison with Python)。 因为之前用Faster R-CNN做过一个红绿灯检测的小实践,但是Git...

learning_tortosie ⋅ 04/12 ⋅ 0

OpenCV中几何形状识别与测量

经常看到有学习OpenCV不久的人提问,如何识别一些简单的几何形状与它们的颜色,其实通过OpenCV的轮廓发现与几何分析相关的函数,只需不到100行的代码就可以很好的实现这些简单几何形状识别与...

gloomyfish ⋅ 04/16 ⋅ 0

【OpenCV系列】【四】操作像素的三种方式

在opencv中,操作像素的方法有三种,每种的速度不同,可以实际使用时测试(测试方法见【OpenCV系列】【三】计算程序运行时间),各有各的好处。 具体代码如下: 可以看出,后面两种方式,需要...

muqiusangyang ⋅ 04/15 ⋅ 0

OPenCV 的安装,环境配置(Windows平台)

1、在官网下载opencv,链接:http://opencv.org/,下载至某盘(推荐D),下载后点击,如下: 随后弹出一个提示框,可不用管它,等一段时间,会解压出一个OpenCV文件夹,其中有如下几个文件: ...

weixin_40647819 ⋅ 04/14 ⋅ 0

Ros图像与Opencv图像的相互转换(C++)

转自:https://blog.csdn.net/qq_27050183/article/details/51141998 Ros图像与Opencv图像的相互转换(C++)(译文*来自wiki)(ROS为indigo版本) 摘要:此教程通过将ROS图像转换为OpenCV图...

qq_39907831 ⋅ 05/29 ⋅ 0

Python各类图像库的图片读写方式总结

转载来源:http://www.cnblogs.com/skyfsm/p/8276501.html Python各类图像库的图片读写方式总结 最近在研究深度学习视觉相关的东西,经常需要写python代码搭建深度学习模型。比如写CNN模型相...

chenxueying1993 ⋅ 04/24 ⋅ 0

OpenCV中高斯混合背景建模算法汇总

引用地址:http://blog.csdn.net/chuhang_zhqr/article/details/51060745  GMM是网上到处可见且用得最多的背景建模算法,论文上很多相关概率公式,又看了很多博客对于GMM的解释,直到现在...

漫步当下 ⋅ 04/20 ⋅ 0

为Visual Studio配置OpenCV

配置的环境是: Windows 8, Visual Studio 2012 openCV_2.47 下面开始详细地讲解整个配置的过程: 步骤1: 首先需要下载openCV,这是Sourceforge的链接:http://sourceforge.net/projects/ope...

Comma_H ⋅ 05/14 ⋅ 0

图片人脸检测(OpenCV版)

图片人脸检测 人脸检测使用到的技术是OpenCV,上一节已经介绍了OpenCV的环境安装,点击查看. 功能展示 识别一种图上的所有人的脸,并且标出人脸的位置,画出人眼以及嘴的位置,展示效果图如下...

vipstone ⋅ 05/21 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java Web如何操作Cookie的添加修改和删除

创建Cookie对象 Cookie cookie = new Cookie("id", "1"); 修改Cookie值 cookie.setValue("2"); 设置Cookie有效期和删除Cookie cookie.setMaxAge(24*60*60); // Cookie有效时间 co......

二营长意大利炮 ⋅ 今天 ⋅ 0

【每天一个JQuery特效】淡入淡出显示或隐藏窗口

我是JQuery新手爱好者,有时间就练练代码,防止手生,争取每天一个JQuery练习,在这个博客记录下学习的笔记。 本特效主要采用fadeIn()和fadeOut()方法显示淡入淡出的显示效果显示或隐藏元...

Rhymo-Wu ⋅ 今天 ⋅ 0

Spring JDBC使用方法

普通实现: 1、创建数据表customer。 可以使用任何数据库实现,在项目中要引入相应数据库驱动包并配置相应数据库连接。 2、创建Customer pojo。 Customer类的属性对应数据库的属性,除了为每...

霍淇滨 ⋅ 今天 ⋅ 0

Contos 7 安装Jenkins

Jenkins是一款能提高效率的软件,它能帮你把软件开发过程形成工作流,典型的工作流包括以下几个步骤 开发 提交 编译 测试 发布 有了Jenkins的帮助,在这5步中,除了第1步,后续的4步都是自动...

欧虞山 ⋅ 今天 ⋅ 0

revel

revel install go get github.com/revel/revelgo get github.com/revel/cmd create new app revel new git.oschina.net/zdglf/myapp run app revel run git.oschina.net/zdglf/myapp ot......

zdglf ⋅ 今天 ⋅ 0

49. Group Anagrams - LeetCode

Question 49. Group Anagrams Solution 思路:维护一个map,key是输入数组中的字符串(根据字符排好序) Java实现: public List<List<String>> groupAnagrams(String[] strs) { Map<Strin......

yysue ⋅ 今天 ⋅ 0

spring Email

使用spring发Email其实就是使用spring自己封装携带的一个javamail.JavaMailSenderImpl类而已。这个类可以当一个普通的java对象来使用,也可以通过把它配置变成spring Bean的方式然后注入使用...

BobwithB ⋅ 今天 ⋅ 0

spark 整理的一些知识

Spark 知识点 请描述spark RDD原理与特征? RDD全称是resilient distributed dataset(具有弹性的分布式数据集)。一个RDD仅仅是一个分布式的元素集合。在Spark中,所有工作都表示为创建新的...

tuoleisi77 ⋅ 今天 ⋅ 0

思考

时间一天天过感觉自己有在成长吗?最怕的是时光匆匆而过,自己没有收获!下面总结下最近自己的思考。 认识自己 认识另一个自己,人们常说要虚心听取别人意见和建议。然而人往往是很难做到的,...

hello_hp ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部