opencv for java给图片添加水印中文问题

Posted luffy5459

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv for java给图片添加水印中文问题相关的知识,希望对你有一定的参考价值。

    opencv提供的给图片添加文字的方法Imgproc.putText()可以给图片添加文字,最后类似一个添加水印的效果,但是这个方法对中文支持不好,在没有字体支持的情况下,默认中文显示?。如下图所示:

    代码如下:

package org.example;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.net.URL;
public class AddWatermark1 
    public static void main(String[] args) 
        try
            URL url = null;
            String os = System.getProperty("os.name");
            if(os.startsWith("Linux"))
                url = ClassLoader.getSystemResource("opencvlib/libopencv_java453.so");
            else
                url = ClassLoader.getSystemResource("opencvlib/opencv_java453.dll");
            
            System.load(url.getPath());
            Mat src= Imgcodecs.imread("C:\\\\Users\\\\86159\\\\Pictures\\\\watermark.png");
            if(src.empty())
                throw new Exception("no file");
            
            Mat dst = src.clone();
            int height = src.height();
            int width = src.width();
            //设置遮罩层
            Imgproc.rectangle(dst,new Point(0,height - 200),new Point(width-2,height-2),new Scalar(50,48,48,158),-1);

            Point p=new Point(0,height-120);
            Point p2 = new Point(0,height-54);
            Point p3 = new Point(width-150,height-80);
            //添加时间
            Imgproc.putText(dst, "2022-04-01 09:21:13", p, 4, 0.8, new Scalar(245,168,1),2);
            //添加地点
            Imgproc.putText(dst, "湖北省武汉市", p2, 4, 0.8, new Scalar(245,168,1),2);
            //添加使用人
            Imgproc.putText(dst, "张三", p3, 4, 0.8, new Scalar(245,168,1),2);

            boolean flag = Imgcodecs.imwrite("watermark.png", dst);
            System.out.println("done."+flag);
            //输出图像
        catch(Exception e)
            System.out.println("例外:" + e);
        
    

    解决这个乱码问题的办法也不是没有,这个好像需要在编译opencv的时候就把字体添加进去。总体来说,还是很麻烦的。

    还有一种原始的办法,就是回到java.awt提供的画图工具上,使用Graphics2D类提供的办法。这里也给出一个代码:

package org.example;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;

public class AddWatermark2 
    private static URL picLocationURL;
    private static URL picTimeURL;
    public static void main(String[] args) 
        String path = "C:\\\\Users\\\\86159\\\\Pictures\\\\watermark.png";
        try 

            URL url = null;
            String os = System.getProperty("os.name");
            if(os.startsWith("Linux"))
                url = ClassLoader.getSystemResource("opencvlib/libopencv_java453.so");
            else
                url = ClassLoader.getSystemResource("opencvlib/opencv_java453.dll");
            
            System.load(url.getPath());
            picLocationURL = ClassLoader.getSystemResource("pic_location.png");
            picTimeURL = ClassLoader.getSystemResource("pic_time.png");
            BufferedImage image = ImageIO.read(new File(path));
            int width = image.getWidth();
            int height = image.getHeight();
            Graphics2D g = image.createGraphics();

            Color fillColor = new Color(50, 48, 48,158);
            g.setColor(fillColor);
            g.fillRect(0,height-200,width,200);
            Color fontColor = new Color(245,168,1);
            g.setColor(fontColor);
            Image locationIcon = new ImageIcon(picLocationURL.getPath()).getImage();
            Image timeIcon = new ImageIcon(picTimeURL.getPath()).getImage();
            g.drawImage(timeIcon,34,height-157,null);
            g.drawImage(locationIcon,34,height-93,null);
            Font font = new Font("微软雅黑",Font.PLAIN,40);
            g.setFont(font);
            g.drawString("2022-04-03 20:53:00",80,height-120);

            g.drawString("湖北省武汉市",80,height-54);
            font = new Font("微软雅黑",Font.PLAIN,44);
            g.setFont(font);
            g.drawString("张三",width-150,height-80);
            g.dispose();
            Mat dst = WeChatQRCodeTool.bufImg2Mat(image,BufferedImage.TYPE_3BYTE_BGR, CvType.CV_8UC3);
            boolean flag = Imgcodecs.imwrite("watermark.png", dst);
            System.out.println("done."+flag);
         catch (IOException e) 
            e.printStackTrace();
        
    

    这种办法加水印的效果如下:

 

     中文问题很好解决。

     这个里面使用了微软雅黑字体,在windows下没有问题,但是部署到linux下,可能缺失微软雅黑字体,所以最终还是会显示中文乱码,这个乱码是因为系统缺失字体,直接拷贝windows系统下的msyh.ttf字体文件(C:\\Windows\\Fonts)到linux字体目录(usr/share/fonts)下新建的目录myfonts即可,系统字体,windows和linux倒是通用的,字体文件要生效,可以执行一个这样的命令:

[root@server myfonts]# fc-cache -fv

     上面提到opencv提供的添加文字Imgproc.putString()要解决中文乱码,需要在opencv提供的依赖库里面编译的时候就安装上字体,显然更麻烦。

以上是关于opencv for java给图片添加水印中文问题的主要内容,如果未能解决你的问题,请参考以下文章

Java使用OpenCV实现人脸识别/人眼检测/图片截取/合成/添加水印

java实现给图片添加水印(文字水印或图片水印)

分享几个用 Python 给图片添加水印的方法,简单实用

js~~给网站图片添加水印~~~

使用ffmpeg给视频添加图片及文字水印

java 给图片和动图添加水印