近期开发了一些有意思的项目,感觉很久都没有再接触过图像处理领域了,有点跟熟悉的陌生人打交道的快感,这里简单记录一下相关算法, 便于后续归档与复现。
我使用的是org.bytedeco.javacv依赖库,不需要编译安装opencv,在java环境下会更为便捷,pom.xml中引入如下依赖:
org.bytedeco javacv1.4.1
纯javacv代码如下,需要注意Javacv的语法与Opencv区别还挺大的,有很多接口不再适配。
import org.bytedeco.javacpp.Loader;
import org.bytedeco.javacpp.opencv_core;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_highgui.cvShowImage;
import static org.bytedeco.javacpp.opencv_highgui.cvWaitKey;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvLoadImage;
import static org.bytedeco.javacpp.opencv_imgproc.*;
public class colorSelect {
//hsv绿色范围
public static opencv_core.CvScalar g_min = cvScalar(35, 43, 46, 0); //HSV色域
public static opencv_core.CvScalar g_max= cvScalar(77, 255, 220, 0); //HSV色域
public static void main(String[] args) {
//读入图片
IplImage orgImg = cvLoadImage("/opt/project/ColorBbox-OpencvTest/test.png");
//rgb->hsv
IplImage hsv = IplImage.create( orgImg.width(), orgImg.height(), orgImg.depth(), orgImg.nChannels() );
cvCvtColor( orgImg, hsv, CV_BGR2HSV );
IplImage imgThreshold = cvCreateImage(cvGetSize(orgImg), 8, 1);
//阈值化
cvInRangeS(hsv, g_min, g_max, imgThreshold);
//形态学闭处理
IplImage Morphology_result = IplImage.create(orgImg.width(),orgImg.height(), IPL_DEPTH_8U, 1);
IplConvKernel kernelCross = cvCreateStructuringElementEx(21, 21,7,7, CV_SHAPE_RECT);
cvMorphologyEx(imgThreshold, Morphology_result, Morphology_result, kernelCross, MORPH_CLOSE, 1);
//膨胀腐蚀
IplImage erosion_dst = IplImage.create(orgImg.width(),orgImg.height(), IPL_DEPTH_8U, 1);
IplImage dilate_dst = IplImage.create(orgImg.width(),orgImg.height(), IPL_DEPTH_8U, 1);
IplConvKernel kernel=cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_RECT);
cvErode( Morphology_result, erosion_dst, kernel,3); //腐蚀
cvDilate( erosion_dst, dilate_dst, kernel,4); //膨胀
//查找轮廓并生成轮廓数组, 画出轮廓矩形
CvMemStorage mem = CvMemStorage.create();
CvSeq contours = new CvSeq();
CvSeq ptr = new CvSeq();
cvFindContours(dilate_dst, mem, contours, Loader.sizeof(CvContour.class) , CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
CvRect boundingBox;
int index = 1;
for (ptr = contours; ptr != null; ptr = ptr.h_next()) {
boundingBox = cvBoundingRect(ptr, 0);
cvRectangle( orgImg , cvPoint( boundingBox.x(), boundingBox.y() ),
cvPoint( boundingBox.x() + boundingBox.width(), boundingBox.y() + boundingBox.height()),
cvScalar( 0, 255, 255, 255 ), 2, 0, 0 );
System.out.println("boundingBox_index" + index + ".x : " + boundingBox.x());
System.out.println("boundingBox_index" + index + ".y : " + boundingBox.y());
System.out.println("boundingBox_index" + index + ".width : " + boundingBox.width());
System.out.println("boundingBox_index" + index + ".height : " + boundingBox.height());
index++;
}
cvShowImage( "Contours", orgImg );
cvWaitKey(0);
}
}
使用七巧板图像进行测试,测试图像如下,这里选择的是HSV色域中的绿色区域:
阈值化后,再经过膨胀腐蚀处理后的效果如下所示:
对颜色轮廓进行提取后,进行颜色区域的标注,标注Bbox效果如下所示,这里将绿色区域都框出来了:
注意cvScalar()的参数为HSV色域值,而不是RBG或BGR。
HSV(Hue, Saturation, Value)是根据颜色的直观特性由A. R. Smith在1978年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。这个模型中颜色的参数分别是:色调(H),饱和度(S),亮度(V)。
色调H:用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;
饱和度S:取值范围为0.0~1.0;
亮度V:取值范围为0.0(黑色)~1.0(白色)。
对于基本色中对应的HSV分量需要给定一个严格的范围,下面是一些颜色的模糊范围:
H: 0— 180
S: 0— 255
V: 0— 255
暂时这样处理,后面有更精确的需求再进行算法优化。
每天都想午休但睡不着的乔木小姐
2021.11.19



