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里每个元素都是所探测到的一个目标。第一个参数是要识别的图片,第二个是结果,第三个是一些更复杂的结果。第四个第五个如下:
//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);