Java调用opencv实现图片去水印
opencv实现图片去水印案例
- Java调用opencv实现图片去水印
- 环境安装配置
- IDEA下开发配置
- 测试案例
Java调用opencv实现图片去水印
最近项目中遇到个需求,图片去水印下载,由于上传时并未保存原图url,查找了相关资料,基本上都是通过设置RGB色值去水印,测试过后效果并不理想,会将图片中颜色跟RGB色值相同的也给去掉,在朋友的推荐下,使用了opecv这款开源软件,而Java调用opencv的例子很少,opencv官网上也没有java相关的api操作文档,期间踩了不少坑,最终在windows上测试通过,并在linux上也运行成功了(linux上效果更好),仅在这里记录下相关步骤,希望后续遇到同问题的人少走弯路。
环境安装配置
opencv官网链接:https://opencv.org/releases/
这里以opencv-4.5.1为例。
- windows环境,官网上选择windows版本下载安装即可,如下所示;
- linux环境,官网上选择sources下载zip压缩包,如下所示;
- 1)将下载好的压缩包放置到linux服务器下(以unbuntu为例),存放位置可自行指定,如 /usr/local/enviroment/opencv,执行解压命令unzip opencv-4.5.1.zip
- 2)进入解压好的目录,新建一个build目录,进入build目录下;
cd opencv-4.5.1
mkdir build
cd build
- 3)下载cmake,并安装相关联的包;
apt install cmake
sudo apt-get install cmake
sudo apt-get install build-essential libgtk2.0-dev libavcodec-dev libavformat-dev libjpeg.dev libtiff4.dev libswscale-dev libjasper-dev
- 4)用cmake生成java的jar;
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTS=OFF ..
- 5)结束后输入如下口令;
make -j8
sudo make install
- 6)安装结果;
build/bin下有opencv-451.jar、build/lib下有libopencv_java451.so文件,表示安装成功
IDEA下开发配置
- 通过maven命令将opencv-451.jar打包至本地maven仓库;
安装指定文件到本地仓库命令:mvn install:install-file
-Dfile=<myfile.jar> : 设置该jar包文件所在的路径与文件名
-DgroupId=<groupId> : 设置上传到仓库的包名
-DartifactId=<artifactId> : 设置该包所属的模块名
-Dversion=1.0.0 : 设置该包的版本号
-Dpackaging=jar : 设置该包的类型(很显然jar包)
如:mvn install:install-file -Dfile=D:/opencv/opencv-451.jar -DgroupId=org.opencv -DartifactId=opencv -Dversion=4.5.1 -Dpackaging=jar
- pom文件中添加maven依赖;
<!-- opencv -->
<dependency><groupId>org.opencv</groupId><artifactId>opencv</artifactId><version>4.5.1</version>
</dependency>
- opencv动态库配置;
通过在application.yml文件中配置动态库路径,并增加配置类,完成配置。
1)application.yml配置如下;
opencv:lib:# linux#path: /usr/local/environment/opencv/opencv-4.5.1/build/lib/libopencv_java451.so#windowspath: D:/opencv/opencv/build/java/x64/opencv_java451.dll
2)配置类如下:
/*** opencv动态库配置* @author wangjiajin* @date 2021/3/2* @desc*/
@Configuration
@ConfigurationProperties(prefix = "opencv.lib")
public class OpenCvLibConfig {@Value("${opencv.lib.path}")private String path;@PostConstructpublic void init() {System.load(path);}
}
测试案例
- 图片工具类
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;/*** 图片工具类* @author wangjiajin* @date 2021/2/23* @desc*/
public class ImageUtils {public static void addWaterMark(String srcImgPath, String waterMarkContent, String waterImgPath) {try {// 读取原图片信息File srcImgFile = new File(srcImgPath);//得到文件Image srcImg = ImageIO.read(srcImgFile);//文件转化为图片int srcImgWidth = srcImg.getWidth(null);//获取图片的宽int srcImgHeight = srcImg.getHeight(null);//获取图片的高int fontSize = (srcImgWidth - 20) / waterMarkContent.length();Font font = new Font("宋体", Font.PLAIN, fontSize);// 加水印BufferedImage bufImg = new BufferedImage(srcImgWidth, srcImgHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g = bufImg.createGraphics();g.drawImage(srcImg, 0, 0, srcImgWidth, srcImgHeight, null);g.setColor(Color.white); //根据图片的背景设置水印颜色g.setFont(font); //设置字体g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.4f));//设置水印的坐标int x = 10;int y = (srcImgHeight) / 2;g.drawString(waterMarkContent, x, y); //画出水印g.dispose();// 输出图片FileOutputStream outImgStream = new FileOutputStream(waterImgPath);ImageIO.write(bufImg, "jpg", outImgStream);outImgStream.flush();outImgStream.close();} catch (Exception e) {e.printStackTrace();}}public static void getMask(String path, String waterMarkContent, String maskPath) {try {Image originImg = ImageIO.read(new File(path));int width = originImg.getWidth(null);int height = originImg.getHeight(null);int fontSize = (width - 20) / waterMarkContent.length();Font font = new Font("宋体", Font.PLAIN, fontSize);BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g = bufImg.createGraphics();g.setBackground(Color.BLACK);g.clearRect(0, 0, width, height);g.setColor(Color.white);g.setFont(font);g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.4f));//设置水印的坐标int x = 10;int y = (height) / 2;g.drawString(waterMarkContent, x, y); //画出水印g.dispose();// 输出图片FileOutputStream outImgStream = new FileOutputStream(maskPath);ImageIO.write(bufImg, "jpg", outImgStream);outImgStream.flush();outImgStream.close();} catch (Exception e) {e.printStackTrace();}}/*** 给定一组url,将此集合地址下对应的资源下载到浏览器** @param urls url地址的集合* @throws IOException*/public static void downloadPic(java.util.List<String> urls, HttpServletResponse response) throws Exception {ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());try {//文件的名称String downloadFilename = "图片.zip";//转换中文否则可能会产生乱码downloadFilename = URLEncoder.encode(downloadFilename, "UTF-8");//指明response的返回对象是文件流response.setContentType("application/octet-stream;charset=UTF-8");//设置在下载框默认显示的文件名response.setHeader("Content-Disposition","attachment;filename="+downloadFilename);for (String url : urls) {String imgName = LocalDateTime.now().toString();String suffix = url.substring(url.lastIndexOf("."));zos.putNextEntry(new ZipEntry(imgName + suffix));InputStream fis = getInputStreamByGet(url);byte[] bytes = new byte[1024];int len;while (true) {assert fis != null;if ((len = fis.read(bytes)) == -1) break;zos.write(bytes, 0, len);}fis.close();}} catch (Exception e) {e.printStackTrace();} finally {zos.flush();zos.close();}}public static InputStream getInputStreamByGet(String url) {try {HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();conn.setReadTimeout(5000);conn.setConnectTimeout(5000);conn.setRequestMethod("GET");if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {return conn.getInputStream();}} catch (IOException e) {e.printStackTrace();}return null;}
}
- 测试方法
//1.启服务通过配置文件运行
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.photo.Photo;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** opencv测试* @author wangjiajin* @date 2021/3/2* @desc*/
@RestController
@RequestMapping("/opencv")
@Api(tags = "opencv测试接口")
public class OpenCvTestController {@PostMapping("/clearWater")@ApiOperation(value = "图片去水印")public String clearWater() {String markContent = "测试生成水印";String waterPath = "D:\\img\\water.jpg";//通过原图加水印获得初始水印图ImageUtils.addWaterMark("D:\\img\\1.png", markContent, waterPath);//蒙版图路径String maskPath = "D:\\img\\mask.jpg";//获取蒙版图,黑底+透明水印字ImageUtils.getMask(waterPath, markContent, maskPath);//opencv读取水印图Mat image = Imgcodecs.imread(waterPath);//opencv读取蒙版Mat mask = Imgcodecs.imread(maskPath, CvType.CV_8UC1);Mat dst = new Mat(image.size(), CvType.CV_8UC3);Photo.inpaint(image, mask, dst, 20, Photo.INPAINT_TELEA);String originPath = "D:\\img\\test.jpg";Imgcodecs.imwrite(originPath, dst);return "成功";}
}//2.通过main方法测试
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.photo.Photo;/*** opencv图片去水印测试* @author wangjiajin* @date 2021/3/2* @desc*/
public class OpencvImageTest {public static void main(String[] args) throws Exception {//加载动态库,main方法无法通过配置文件加载System.load("D:\\opencv\\opencv\\build\\java\\x64\\opencv_java451.dll");String markContent = "测试生成水印";String waterPath = "D:\\img\\water.jpg";//通过原图加水印获得初始水印图ImageUtils.addWaterMark("D:\\img\\1.png", markContent, waterPath);//蒙版图路径String maskPath = "D:\\img\\mask.jpg";//获取蒙版图,黑底+透明水印字ImageUtils.getMask(waterPath, markContent, maskPath);//opencv读取水印图Mat image = Imgcodecs.imread(waterPath);if (image.empty()) {throw new Exception("image is empty");}//opencv读取蒙版Mat mask = Imgcodecs.imread(maskPath, CvType.CV_8UC1);Mat dst = new Mat(image.size(), CvType.CV_8UC3);Photo.inpaint(image, mask, dst, 20, Photo.INPAINT_TELEA);HighGui.imshow("原图", image);HighGui.imshow("蒙版", mask);HighGui.imshow("结果", dst);String originPath = "D:\\img\\test.jpg";Imgcodecs.imwrite(originPath, dst);HighGui.waitKey();}
}
- 可能遇到的错误
org.opencv.imgcodecs.Imgcodecs.imread_1(Ljava/lang/String;)J
//解决方法,将pom中热部署依赖去掉即可
<!-- 热部署 -->
<!--<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency>-->
- 测试结果
Java调用opencv实现图片去水印相关推荐
- 基于Ubuntu系统,调用opencv在图片上显示数字和汉字
文章目录 一.汉字编码的介绍 1.汉字编码的发展过程 (1)汉字编码产生的原因 (2)常用的汉字编码 2.区位码 (1)产生原因 (2)概念简述 (3)区域分布情况 3.机内码 (1)基本概念 (2) ...
- 图像文字识别(二):java调用tesseract 识别图片文字
在JAVA中调用tesseract识别图片的文字内容,主要有两种方式:cmd方式,tess4j方式.在这篇博客中,主要记录一下通过cmd命令行的方式.cmd方式,就是通过在java中调用命令行,来 ...
- Ubuntu 下调用 opencv 在图片显示汉字和数字
目录 实验要求: 1 环境准备 1.1创建文件 实验要求: 学习理解汉字的机内码.区位码编码规则和字形数据存储格式.在Ubuntu下用C/C++(或python) 调用opencv库编程显示一张图片, ...
- python + opencv微博图片去水印
python 3.6.5 openCV 4.0.1 基本思路: 提取ROI(感兴趣的区域,即水印所在的区域) 为水印创建蒙层 借助水印蒙层对图片进行修补 **提取ROI:**获取水印在图片中所在的区域 ...
- Java调用OpenCV来识别面部或眼睛
文章目录 前言 一.OpenCV是什么? 二.使用步骤 1.引入库 2.代码示例 总结 前言 随着人工智能的不断发展,计算机视觉这门技术也越来越重要,很多人都开启了学习计算机视觉,本文就介绍了计算机视 ...
- Java使用Tesseract-OCR文字识别(Java调用tess4j提取图片中文、英文、数字信息)
由于需要在应用中将原本的身份认证手动提交身份信息改为用户上传身份证照自动提取信息,提升用户体验,第一时间想到阿里云等平台的收费服务及开源技术Tesseract-OCR(Tesseract-OCR提供了 ...
- c++调用opencv实现图片叠加以及添加水印效果
前言 本篇文章参考了以下文章: https://blog.csdn.net/mars_xiaolei/article/details/78791133 https://answers.opencv.o ...
- python调用opencv放大图片
代码如下,简单易懂: import cv2# 横纵轴放大比例 fx = 2 fy = 2 img = cv2.imread('frame_000001.jpg') enlarge = cv2.resi ...
- python 调用opencv查看图片尺寸
代码如下,简单易懂: import cv2img_path = 'frame_000001.jpg' img = cv2.imread(img_path) size = img.shape # ==& ...
最新文章
- 推荐系统实践整体化总结
- RocketMQ:Consumer概述及启动流程与消息拉取源码分析
- 简书-一个集优雅文艺和Markdown于一身的网站
- perl学习4--调用子程序
- nfc标签 方案 防伪_NFC技术解读及ST NFC产品与方案
- Python报错:UnicodeDecodeError: 'gbk' codec can't decode byte 0xae in position 199: illegal multibyte s
- 静态库和动态库(转)
- SAP UI5 应用开发教程之十七 - 聚合绑定在 UI5 复合控件中的使用
- 猎户座计划软件测试,四核配置跑分:猎户座4412性能强劲_平板电脑评测-中关村在线...
- inputstream示例_Java InputStream available()方法与示例
- 作为程序员,起码要知道的 Python 修饰器!
- TP-Link 开始锁定路由器固件禁止安装开源固件
- excel 单元格文本链接方法
- 巧用 TypeScript(四)
- vbs编程-执行cmd命令
- 计算机网络安全及防火墙技术任务书,《毕业设计(论文)-计算机网络安全技术分析》.doc...
- 目标检测中常见指标 AP MAP coco Pascal voc 评价指标说明
- 微信小程序常见面试题总结
- 一些基础知识:脑科学、神经科学、心理学
- window10安装minio