文章目录
    
    
    
    
     - 
      库加载
     
- 
      图像读取
     
- 
      色域转换
     
- 
      直方图均衡化
     
- 
      输出二值图像
     
- 
      处理噪点
     
- 
      轮廓识别
     
- 
      结果处理
     
- 
      轮廓绘制
     
     
    
    
     Java使用OpenCV进行颜色识别
    
    
     流程
    
    
     - 
      库加载
     
- 
      图像读取
     
- 
      色域转换
     
- 
      直方图均衡化(选用)
     
- 
      输出二值图像
     
- 
      噪点处理
     
- 
      轮廓识别
     
- 
      结果解析
     
     详细步骤
    
    
     库加载
    
    
     System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
     
    
     图像读取
    
    
     将图片读入到Mat中
    
    
     Mat srcImgMat = Imgcodecs.imread(filename);
     
    
     色域转换
    
    
     读入的如果是RGB格式的文件,首先将图片转换到HSV色域中。具体什么事HSV自行百度。(选做。如果色彩情况复杂或者动态变化范围较大,建议)
    
    
     Imgproc.cvtColor(srcImgMat, desImaMat, Imgproc.COLOR_RGB2HSV);
     
    
     直方图均衡化
    
    
     直方图均衡化可以增加颜色之间的对比度,更容易识别轮廓。由于目标颜色比较简单,所以此处略过。
    
    
     输出二值图像
    
    
     这里给出想要识别的颜色的阈值范围,使用的是HSV色域。
     
      如果你在一开始没有转换到HSV色域,则继续使用BGR来确定阈值的范围。
     
     
     opencv HSV色域范围是H:0-179, S:0-255, V:0-255
     
     建议此处根据不同场景多做调试。
    
    
     
      写一个简单的有滑块的gui调试窗口并调用inRange,然后实时显示更方便调试。
     
    
    
     //以蓝色为例
	Scalar lowerbScalar = new Scalar(100,50,50); //hsv色域的蓝色最低阈值
	Scalar highbScalar = new Scalar(130, 255, 255); //hsv色域蓝色最高阈值
	//获得二值图像。结果存到desImgMag
	Core.inRange(desImgMat, lowerbScalar, highbScalar, desImgMat);
     
    
     处理噪点
    
    
     上一步的结果可以直接通过显示出来;
    
    
     HighGui.imshow(desImgMat);
HighGui.waitkey(0);
     
    
     如果现实的二值图像噪点比较多,需要清除噪点。
    
    
     //open processing 去除噪点,小于5x5的都将忽略
		Mat kernel =  Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5,5));
		//close processing ,连通区域
		Imgproc.morphologyEx(desImgMat, desImgMat, Imgproc.MORPH_CLOSE, kernel);
     
    
     处理完后,可以再现实图片查看效果。
    
    
     轮廓识别
    
    
     List<MatOfPoint> pointsVector = new Vector<MatOfPoint>();
		Mat hierarchy = new Mat();
		Imgproc.findContours(desImgMat, pointsVector, hierarchy, 		 Imgproc.RETR_CCOMP,Imgproc.CHAIN_APPROX_SIMPLE);
     
    
     这个函数返回值是一个pointsVector。这个Vector里每个元素都是所探测到的一个目标。第一个参数是要识别的图片,第二个是结果,第三个是一些更复杂的结果。第四个第五个如下:
    
    
     - 
      Imgproc.RETR_CCOMP 提取所有轮廓,还有其他的参数,比如RETR_EXTERNAL是提取外层轮廓。
     
- 
      Imgproc.CHAIN_APPROX_SIMPLE 压缩水平和垂直方向,只保存对角线方向的元素。例如矩形轮廓只需要4个点来保存信息。
      
 其他的参数自行去官网的文档查阅即可。
     结果处理
    
    
     //result processing
		//!!!如果有多个目标,需要表里整个pointsVector
		MatOfPoint cntMatOfPoint = pointsVector.get(0);
		Rect rect = Imgproc.boundingRect(cntMatOfPoint);
		int x = rect.x;
		int y = rect.y;
		int w = rect.width;
		int h = rect.height;
     
    
     由于我测试的只有一个待检测物体,所以只取了第0个。
     
     这样就得到了矩形轮廓。
    
    
     轮廓绘制
    
    
     将目标用红色矩形圈起来。如果想得到坐标,就直接通过x,y,w,h计算就行。
    
    
     //Draw the rectangle outline
		Imgproc.rectangle(srcImgMat, new Point(x,y), new Point(x+w, y+h) , new Scalar(0,0,255));;
		String window_name = "show";
		HighGui.imshow(window_name,desImgMat);
		HighGui.imshow(window_name, srcImgMat);
		HighGui.waitKey(1);