想做图片识别,但是大厂只提供接口,看不到实际代码,只能自己来动手了.这篇文章主要是介绍如何从一张图片里面提取色彩边界,用于后面做特征分析,算是基础部分.

图片处理步骤

  • 使用 Thumbnails 工具包将图片等比压缩到指定大小
  • 使用 JDK 自带的 BufferedImage 类灰度化图片
  • 通过判断一个像素和它相邻像素的颜色是否相近,来确定是不是色彩边界点,如果不是边界点,就把它设置为白色.
  • 除了图片最外围的一圈像素点之外,其他所有像素点依次执行第三步
  • 将处理结果打印到text文档中

引入jar包:

<!-- java图片工具 https://mvnrepository.com/artifact/net.coobird/thumbnailator -->
<dependency><groupId>net.coobird</groupId><artifactId>thumbnailator</artifactId><version>0.4.12</version>
</dependency>

实现代码如下:

import net.coobird.thumbnailator.Thumbnails;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.charset.StandardCharsets;public class ImageUtil {// 获取图片线条边界用// 阈值越大,空白越多// 值3000000适用于色彩分明的图片,如卡通人物蜡笔小新// 值1000000适用于色彩过渡平缓的图片,如3D卡通今年我们十七八岁private static final int threshold = 1000000;// 生成文本宽度// 值100适用于商标,头像等小图片// 值400适用于复杂,内容丰富的大图片private static final int picWidth = 400;public static void main(String[] args) throws IOException {String fromPic = "C:\\Users\\Public\\Pictures\\Sample Pictures\\241707553465767.png";String toTxt = "d:\\test5.txt";BufferedImage bufferedImage = ImageIO.read(new File(fromPic));// 1.压缩图片BufferedImage compactImage = Thumbnails.of(bufferedImage).size(picWidth, 1000).asBufferedImage();// 2.灰度化BufferedImage grayImage = grayingImage(compactImage);// 3.二值化//BufferedImage binaryImage = binaryImage(grayImage);// 4获取边界BufferedImage borderImage = getImageBorder(grayImage);// 5.输出到txt文本writeToTxt(borderImage, toTxt);// 6.保存图片File newFile = new File("d:\\test8.jpg");ImageIO.write(borderImage, "jpg", newFile);}/*** 灰度化图片* @param bufferedImage 原图片* @return 灰度化之后的图片*/private static BufferedImage grayingImage(BufferedImage bufferedImage) {BufferedImage grayImage = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(),BufferedImage.TYPE_BYTE_GRAY);for (int i = 0; i < bufferedImage.getWidth(); i++) {for (int j = 0; j < bufferedImage.getHeight(); j++) {int color = bufferedImage.getRGB(i, j);grayImage.setRGB(i, j, color);}}return grayImage;}/*** 二值化图片* @param bufferedImage 原图片* @return 二值化后的图片*/private static BufferedImage binaryImage(BufferedImage bufferedImage) {BufferedImage grayImage = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), bufferedImage.getType());int threshold = getMeanThreshold(bufferedImage);for (int i = 0; i < bufferedImage.getWidth(); i++) {for (int j = 0; j < bufferedImage.getHeight(); j++) {int color = bufferedImage.getRGB(i, j);int r = (color >> 16) & 0xff;int g = (color >> 8) & 0xff;int b = color & 0xff;int gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);if (gray > threshold) {// 白色grayImage.setRGB(i, j, 0xFFFFFF);}else {// 黑色grayImage.setRGB(i, j, 0);}}}return grayImage;}/*** 获取图片的阀值,采用基于灰度平均值的阈值* @param bufferedImage 原图片* @return 二值化的阈值*/private static int getMeanThreshold(BufferedImage bufferedImage) {int w = bufferedImage.getWidth();int h = bufferedImage.getHeight();int num = 0;int sum = 0;for(int i=0; i<w; i++) {for(int j = 0; j < h; j++) {int color = bufferedImage.getRGB(i, j);int r = (color >> 16) & 0xff;int g = (color >> 8) & 0xff;int b = color & 0xff;int gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);sum += gray;num += 1;}}// 测试表明,阀值取平均值的1.2倍效果最好。int threshold = sum / num;if(threshold * 1.2 < 255) {threshold = (int)(1.2 * sum / num);}System.out.println("width: " + w + " height: " + h + " threshold: " + threshold);return threshold;}/*** 输出 0,1 TXT文本*/public static void writeToTxt(BufferedImage bufferedImage, String toSaveFilePath) {File file = new File(toSaveFilePath);try {Writer writer = new OutputStreamWriter(new FileOutputStream(file, true), StandardCharsets.UTF_8);StringBuilder builder = new StringBuilder();for (int j = 0; j < bufferedImage.getHeight(); j++) {for(int i = 0; i < bufferedImage.getWidth(); i++) {int color = bufferedImage.getRGB(i, j);if(color == -1) {builder.append("  ");}else {builder.append("0 ");}}builder.append("\r\n");}writer.write(builder.toString());writer.close();}catch (Exception e) {e.printStackTrace();}}/*** 提取二值化后图片的边界* 对二维码有奇效* @param bufferedImage 原图片* @return 二值化后的图片*/private static BufferedImage getImageBorder(BufferedImage bufferedImage) {BufferedImage borderImage = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), bufferedImage.getType());//List<String> toDealPoints = new ArrayList<>();int imgWidth = bufferedImage.getWidth();int imgHeight = bufferedImage.getHeight();for (int i = 1; i < imgWidth - 1; i++) {for (int j = 1; j < imgHeight - 1; j++) {// 当前点int color = bufferedImage.getRGB(i, j);// 上点int upColor = bufferedImage.getRGB(i, j - 1);// 下点int downColor = bufferedImage.getRGB(i, j + 1);// 左点int leftColor = bufferedImage.getRGB(i - 1, j);// 右点int rightColor = bufferedImage.getRGB(i + 1, j);// 如果某个黑点的上下左右点都为黑点,就表示它不是边界,把它设为白点if(isQualified(color, upColor, downColor, leftColor, rightColor)) {// 白色borderImage.setRGB(i, j, 0xFFFFFF);}else {// 原色不变borderImage.setRGB(i, j, color);}}}return borderImage;}/*** 根据设置的阈值,判断当前点是否是边界点* 判断规则如下:* 如果当前点是白色的点,直接跳过* 如果当前点不是白色,且它的上下左右4个点和它的差别都在阈值内,* 那么就认为它不是边界点,返回true,否则返回false;* @param color 当前点* @param upColor 上点* @param downColor 下点* @param leftColor 左点* @param rightColor 右点* @return 是否设置为白色*/public static boolean isQualified(int color, int upColor, int downColor, int leftColor, int rightColor) {// color == -1 表示白色,白色的不需要再设置为白色return color != -1 && (Math.abs(color - upColor) < threshold&& Math.abs(color - downColor) < threshold&& Math.abs(color - leftColor) < threshold&& Math.abs(color - rightColor) < threshold);}}

打印效果:

总结

  • 图片名字叫今年我们十七八岁,处理后的边界还是蛮清楚的
  • 对于噪点处理,后面还需要加上
  • 另外复杂的图片,可以划分为几块,不同的版块使用不同的阈值,不然有些区域的边界很清晰,有些就很模糊
  • 图片不大还可以整体遍历,后面如果需要处理的图片多,效率就不行了.

使用java提取图片的色彩边界相关推荐

  1. Java提取图片文字 tess4j

    1.下载中文语言包 https://tesseract-ocr.github.io/tessdoc/Data-Files 下载 chi_sim.traineddata 2.maven依赖 <!- ...

  2. java提取图片位置信息_实战项目——获取图片中的GPS位置信息和拍摄时间

    今天突然看到有人写过获取图片中位置信息的程序.我觉得很有趣,也就自己实践了一下,研究了一下 话不多说,先上代码 1 #!/usr/bin/env python3 2 #-*- coding: utf- ...

  3. java提取图片base64,如何把

    问题: 在前端如何将image转成base64编码? 回答: 要实现这个功能,要使用canvas来做,Canvas里面提供了一个toDataURL的接口,可以用这个接口获得图片的base64 所以思路 ...

  4. java提取word中的图片_Java怎么获取Word批注的文字和图片

    Java怎么获取Word批注的文字和图片 发布时间:2020-06-23 11:07:08 来源:亿速云 阅读:119 作者:Leah 这篇文章将为大家详细讲解有关Java获取Word批注的文字和图片 ...

  5. java 图片识别提取_老司机帮您Java 提取/读取PDF中的图片

    电脑现已成为我们工作.生活和娱乐必不可少的工具了,在使用电脑的过程中,可能会遇到Java 提取/读取PDF中的图片的问题,如果我们遇到了Java 提取/读取PDF中的图片的情况,该怎么处理怎么才能解决 ...

  6. java提取word中的图片

    一.项目中需要用到word的导入,word 里面的内容由图片,文本,公式等,步骤为:将文档另存为xml格式 1.提取图片,如下是word xml 中的图片标签,具体分析下内容,首先需要获取 w:dra ...

  7. Java提取视频中的音频

    话不多说,上代码 Scanner scanner = new Scanner(System.in);System.out.println("请输入被提取音频的视频:");Strin ...

  8. java修改图片宽高

    java修改图片的宽高 因为一些特定的原因,限制了长传图片的大小.可以使用一下这个方法试试. 我是测试过没问题发布的. import java.awt.Graphics; import java.aw ...

  9. 利用几种颜色量化方法提取图片颜色色调

    利用几种颜色量化方法提取图片颜色色调 利用几种颜色量化方法提取图片颜色色调 1 k-means方法(在RGB空间) 2 k-means方法(Lab颜色空间) 3 最小方差量化方法rgb2ind() 4 ...

最新文章

  1. 使用rancher对Docker容器服务升级
  2. 代码规范性与品质问题~
  3. typeof 与 js数据类型
  4. 通过案例学调优之--Oracle Cluster Table
  5. COMMIT WORK关键字在CRM content management应用里的使用场景
  6. Python开发一个股票类库
  7. 一个实例带你搞懂Apriori关联分析算法
  8. 前端组件化思想与实践
  9. linux下如何添加定时备份任务,Linux下Oracle设置定时任务备份数据库的教程
  10. edup网卡 linux,应用笔记--使用USB WiFi网卡
  11. 使用 Ajax 上传文件
  12. 联想键盘sk8821的Fn功能键
  13. .NET 通过Word模板,使用AsposeWord进行数据动态导出Word
  14. 爬虫不借助浏览器登录_借助Android音乐播放器和旅行组合踏上道路
  15. python计算三角形面积_利用python计算三角形的面积
  16. 恢复matlab文件关联
  17. filp/whoops
  18. 小白装openstack(二) 安装NTP服务
  19. ubuntu下的opencv下载编译安装
  20. (灵魂拷问)MySQL数据库高频面试题,助你脱颖而出

热门文章

  1. golong实现邮件发送
  2. python学习随笔—MacOS卡特琳娜下终端shell变成zsh后anaconda命令失效的解决
  3. 用JAVA实现基于Actor模型的RPC
  4. VC调用C#的COM组件(DLL)
  5. java assertthat_java,junit_juit 用assertThat 提示我找不到符号,java,junit - phpStudy
  6. cookie获取方法
  7. 表格已死,可视当立——给数据穿上美丽的外衣
  8. vulnhub-DC-8靶机渗透记录
  9. 无限火力是哪个服务器2019,2019年英雄联盟无限火力结束时间,预测2020年开启无限火力的时间...
  10. Python string编码