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提供的依赖库里面编译的时候就安装上字体,显然更麻烦。

Java 中为视频添加水印,通常可以使用第三方库或调用外部工具(如 `FFmpeg`)来实现。以下是几种常见的方法和对应的库: ### 使用 FFmpeg `FFmpeg` 是一个功能强大的多媒体处理工具,支持视频、音频的编码、解码、转码以及叠加水印等操作。虽然它本身不是 Java 库,但可以通过 Java 调用其命令行接口来完成任务。 ```java import java.io.IOException; public class AddWatermark { public static void main(String[] args) throws IOException { String videoFile = "path/to/your/video.mp4"; String watermarkImage = "path/to/your/watermark.png"; String outputVideo = "path/to/output/video_with_watermark.mp4"; // 构造 FFmpeg 命令 ProcessBuilder processBuilder = new ProcessBuilder( "ffmpeg", "-i", videoFile, "-i", watermarkImage, "-filter_complex", "overlay=10:10", outputVideo); // 启动进程 Process process = processBuilder.start(); // 等待进程执行完成 try { int exitCode = process.waitFor(); System.out.println("FFmpeg process exited with code " + exitCode); } catch (InterruptedException e) { e.printStackTrace(); } } } ``` 上述代码通过 `ProcessBuilder` 调用了 FFmpeg 的命令行,并使用了 `-filter_complex overlay=10:10` 参数将图片叠加到视频上,其中 `overlay=10:10` 表示水印的位置偏移量(水平方向 10 像素,垂直方向 10 像素)[^1]。 ### 使用 JavaCV `JavaCV` 是基于 OpenCV 和 FFmpeg 的封装库,提供了 Java 接口用于图像和视频处理。通过 JavaCV,可以直接在 Java 中操作视频并添加水印。 ```java import org.bytedeco.javacv.*; import org.bytedeco.opencv.opencv_core.IplImage; import static org.bytedeco.opencv.global.opencv_imgcodecs.cvLoadImage; public class WatermarkWithJavaCV { public static void main(String[] args) throws Exception { FFmpegFrameGrabber grabber = FFmpegFrameGrabber.createDefault("path/to/your/video.mp4"); FFmpegFrameRecorder recorder = FFmpegFrameRecorder.createDefault("path/to/output/video_with_watermark.mp4", grabber.getImageWidth(), grabber.getImageHeight()); grabber.start(); recorder.setFrameRate(grabber.getFrameRate()); recorder.start(); IplImage watermark = cvLoadImage("path/to/your/watermark.png"); Frame frame; while ((frame = grabber.grab()) != null) { // 将帧转换为 IplImage 格式以便进行叠加操作 IplImage image = converter.get().convert(frame); // 在指定位置叠加水印 CvRect roi = new CvRect(10, 10, watermark.width(), watermark.height()); IplImage subImage = cvGetSubRect(image, roi); cvAddWeighted(subImage, 0.5, watermark, 0.5, 0, subImage); // 将处理后的帧写入输出文件 recorder.record(converter.get().convert(image)); } // 释放资源 recorder.stop(); grabber.stop(); } } ``` 上述代码展示了如何利用 JavaCV 加载视频流,逐帧读取并叠加水印图像,最后将处理后的帧写入新的视频文件中 [^4]。 ### 使用其他工具或框架 除了 FFmpeg 和 JavaCV,还可以结合一些自定义的图像处理逻辑来实现水印效果。例如,对于简单的水印需求,可以手动编写代码加载每一帧,然后使用 Java 的 `BufferedImage` 类对图像进行处理并重新生成视频。然而,这种方法通常效率较低,且实现复杂度较高。 --- ###
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luffy5459

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值