年底冲KPI很多项目要结项,临时被拉去开发了一些“很有意思”的项目,感觉自从离开学校以后很长时间都没有再接触过图像处理领域了,有点跟熟悉的陌生人打交道的快感。这里简单记录一下相关代码实现,便于后续归档与复现。
使用纯JavaCV实现图像处理
写在前面:
之前读研的时候在学校偶尔做图像预处理,都是使用的OpenCV图像库,用Python或C++语言进行图像处理编程的时候都很方便。但Java Web的服务端在银河麒麟或CentOS等Linux系统下部署时,该依赖库着实有些水土不服,每次都需要重新编译动态链接库不说,光是离线编译OpenCV库本身就费老劲了。无奈只能撸起袖子用Java重写相关的计算库与方法,想着可否跳过OpenCV封装好的函数,采用原生的写法。
(1)轮廓提取与颜色分割处理
我使用的是org.bytedeco.javacv
依赖库,不需要编译安装opencv,在java环境下会更为便捷,pom.xml
中引入如下依赖:
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.1</version>
</dependency>
纯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.*;
/**
* 颜色分割变换
* rina 2021.11.14
*/
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()