java+opencv实现图像矫正,并解决中文文件名报错问题,同时兼容windows、linux两个环境

前言

java+opencv实现图像矫正,并解决中文文件名报错问题,同时兼容windows、linux两个环境

一、实现效果

矫正前效果图:
矫正前
矫正后效果:
矫正后

二、前期准备

需要引入对应环境#的.dll(windows)与.so(linux)文件,将文件下载到本地,拷贝文件路径替换代码中对应的路径,下载文件资源地址(包含一张测试图片):https://pan.baidu.com/s/1O9WKeD9KU6qEYLYSvbfBjg
提取码:38uv

二、代码部分

1.引入库

直接引入javacv依赖会很臃肿,精简一下只引入opencv部分即可;如需要javacv其他依赖包,根据实际情况引入。
pom依赖:

<dependency>
	<groupId>org.bytedeco</groupId>
	<artifactId>opencv</artifactId>
	<version>4.5.1-1.5.5</version>
</dependency>

2.代码

图像矫正功能代码组成为工具类(RectifyImageUtil)+入参对象(Image)
Image代码如下:

import lombok.Data;
import java.io.Serializable;

/**
 * 图像信息
 * @Date 2023/3/24 9:42
 */
@Data
public class Image implements Serializable {
    
    
    /**
     * 写入图片路径
     */
    private String imgUrlInput;
    /**
     * 输出图片路径(如果为空,将覆盖写入图片路径)
     */
    private String imgUrlOut;
    /**
     * 左上x
     */
    private float ltX;
    /**
     * 左上y
     */
    private float ltY;
    /**
     * 右上x
     */
    private float rtX;
    /**
     * 右上y
     */
    private float rtY;
    /**
     * 左下x
     */
    private float lbX;
    /**
     * 左下y
     */
    private float lbY;
    /**
     * 右下x
     */
    private float rbX;
    /**
     * 右下y
     */
    private float rbY;
    /**
     * 图像宽
     */
    private float imgWidth;
    /**
     * 图像高
     */
    private float imgHeight;
}

RectifyImageUtil代码如下:

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import javax.imageio.ImageIO;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.DataBufferByte;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;

/**
 * @author lqt
 * @date 2023/3/24 9:48
 * @version 1.0
 */
@Slf4j
public class RectifyImageUtil {
    
    

    // 根据服务器环境动态加载依赖 (只支持windows与linux)
    static {
    
    
        String os = System.getProperty("os.name");
        log.info("当前环境" + os);
        if (os != null && os.toLowerCase().startsWith("windows")) {
    
    
            //Windows操作系统
            // todo 替换本地 .dll文件路径 (例如:D:\\data\\windows\\x64\\opencv_java460.dll)
            System.load("(.dll文件本地路径)\\opencv_java460.dll");
        } else if (os != null && os.toLowerCase().startsWith("linux")) {
    
    
            //Linux操作系统
            // todo 部署服务器修改.so文件路径 (例如:/data/so/libopencv_java460.so)
            System.load("(.so文件服务器路径)/libopencv_java460.so");
        }
    }

    public static void main(String[] args) {
    
    
        Image img = new Image();
        img.setImgUrlInput("(测试图片路径,可以使用网片链接中的图片测试)\\qiaoba_副本.png");
        img.setImgUrlOut("(输出图片路径)\\qiaoba_中文2.png");
        // 以下数值是网盘链接图片的测试数据,如果有自己图片和数据直接替换
        img.setLtX(71.5f);
        img.setLtY(112);
        img.setRtX(298.5f);
        img.setRtY(113);
        img.setLbX(53.5f);
        img.setLbY(573);
        img.setRbX(306.5f);
        img.setRbY(624);
        img.setImgWidth(600);
        img.setImgHeight(800);
        boolean flag = rectifyImage(img);
        log.info("操作:" + flag);
    }

    /**
    * 图像矫正
    * @date 2023/3/24 10:10
    * @param img 矫正信息
    * @return boolean
    * @author lqt
    */
    public static boolean rectifyImage(Image img){
    
    
        try {
    
    
            if(StringUtils.isEmpty(img.getImgUrlInput())){
    
    
                return false;
            }
            File file = new File(img.getImgUrlInput());
            if(!file.exists()){
    
    
                return false;
            }
            Mat src = imRead(img.getImgUrlInput());
            Mat dst = new Mat();
            // 输入图像
            Point[] pt1 = new Point[4];
            pt1[0]=new Point(img.getLtX(),img.getLtY());
            pt1[1]=new Point(img.getRtX(),img.getRtY());
            pt1[2]=new Point(img.getLbX(),img.getLbY());
            pt1[3]=new Point(img.getRbX(),img.getRbY());

            //输出图像
            Point[] pt2 = new Point[4];
            pt2[0]=new Point(0,0);
            pt2[1]=new Point(img.getImgWidth(),0);
            pt2[2]=new Point(0,img.getImgHeight());
            pt2[3]=new Point(img.getImgWidth(),img.getImgHeight());

            MatOfPoint2f mop1 = new MatOfPoint2f(pt1);
            MatOfPoint2f mop2 = new MatOfPoint2f(pt2);

            Mat perspectiveMat = Imgproc.getPerspectiveTransform(mop1, mop2);
            Imgproc.warpPerspective(src,dst,perspectiveMat,new Size(img.getImgWidth(),img.getImgHeight()));
            // 输出图像路径为空,覆盖输入图像
            imWrite(dst,StringUtils.isEmpty(img.getImgUrlOut()) ? img.getImgUrlInput() : img.getImgUrlOut());
        }catch (Exception e){
    
    
            log.info("图像矫正异常:", e);
            return false;
        }
        return true;
    }

    /**
     * 读取图像
     * @param filePath 文件路径,可以包含中文
     * @return Mat
     * @author lqt
     */
    public static Mat imRead(String filePath){
    
    
        Mat mat = null;
        try {
    
    
            //使用java2D读取图像
            BufferedImage image = ImageIO.read(new FileInputStream(filePath));
            BufferedImage convertToRgbFormatImage = convertToRgbFormat(image);
            byte[] data = ((DataBufferByte) convertToRgbFormatImage.getRaster().getDataBuffer()).getData();
            mat = new Mat(image.getHeight(), convertToRgbFormatImage.getWidth(), CvType.CV_8UC3);
            mat.put(0, 0, data);
            // 小型图片可以输出 查看下
//            HighGui.imshow("book",src);
//            HighGui.waitKey(0);
        } catch (Exception e) {
    
    
            log.error("读取图像出现异常:", e);
        }
        return mat;
    }

    /**
     * BufferedImage均转为TYPE_3BYTE_BGR,RGB格式
     *
     * @param input 未知格式BufferedImage图片
     * @return TYPE_3BYTE_BGR格式的BufferedImage图片
     * @author lqt
     */
    public static BufferedImage convertToRgbFormat(BufferedImage input) {
    
    
        if (BufferedImage.TYPE_3BYTE_BGR != input.getType()){
    
    
            BufferedImage inputRgb = new BufferedImage(input.getWidth(), input.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
            new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_sRGB), null).filter(input, inputRgb);
            return inputRgb;
        } else{
    
    
            return input;
        }
    }

    /**
     * 保存mat到指定路径
     * @param mat 要保存的Mat
     * @param filePath 保存路径
     * @author lqt
     */
    public static void imWrite(Mat mat, String filePath){
    
    
        try {
    
    
            File file = new File(filePath);
            String fileName = file.getName();
            String fileType = "";
            if(fileName.contains(".")){
    
    
                fileType = fileName.substring(fileName.lastIndexOf("."));
            }
            // 将mat转为java的BufferedImage
            MatOfByte mob = new MatOfByte();
            Imgcodecs.imencode(fileType, mat, mob);
            BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(mob.toArray()));
            String type = fileType.substring(fileType.lastIndexOf(".") + 1).toUpperCase();
            ImageIO.write(bufferedImage, type, new File(filePath));
        } catch (Exception e) {
    
    
            log.error("保存文件出现异常:", e);
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_39310051/article/details/129784755