基于Java BufferedImage实现识别图片中的黑色矩形

前言:在项目中需要实现将图片中的黑色矩形替换为其他图形,其中的难点在于图片中存在其他黑点或者黑色小方块。

实现思路:

二值化,将纯黑的区域保留下来,其他区域编程白色。

去噪:去除噪点

转为矩阵,将黑色像素点的位置的值设为1,其他位置的值设为0

求极大全为1的子矩阵,使用悬吊法求极大全为1的子矩阵

二值化代码:

public static void binaryImage(String filePath,double threshold){

try {

BufferedImage image = ImageIO.read(new File(filePath));

int minX = 0;//图片起始点X

int minY = 0;//图片起始点Y

int width = image.getWidth();//图片的宽度

m = width;

int height = image.getHeight();//图片的高度

n = height;

//将黑色区域化为1,其他为0

for (int i = minX; i < width; i++) {

for (int j = minY; j < height; j++) {

Object data = image.getRaster().getDataElements(i, j, null);//获取该点像素,并以object类型表示

int red = image.getColorModel().getRed(data);

int blue = image.getColorModel().getBlue(data);

int green = image.getColorModel().getGreen(data);

if(red==0&&green==0&&blue==0){

a[i+1 ][j+1 ] = 1;

}

}

}

}catch (IOException e) {

e.printStackTrace();

}

}

去噪:

public static void removeNoise(int whiteThreshold,int blackThreshold){

int i,j,nValue,nCount,m,n;

int nWidth=Calculate.maxn;

int nHeight=Calculate.maxn;

//对图像上下边缘去噪

for(i=0;i

a[i][0]=0;

a[i][nHeight-1]=0;

}

//对图像上下边缘去噪

for( i=0;i

a[0][i]=0;

a[0][nWidth-1]=0;

}

//根据周围点的颜色去噪

//遍历所有的点 //j是y, i是x

for(i=1;i

for( j=1;j

nValue=a[i][j];

if(nValue==1&&whiteThreshold!=0){//如果一点是黑点

nCount=0;

//遍历他周围的八个点,如果他

for(m=j-1;m<=j+1;m++){

for(n=i-1;n<=i+1;n++){

if(a[n][m]==0){//周围白点的个数

nCount++;

}

}

}

if(nCount>=whiteThreshold){//周围白点的个数大于阈值则变为白色

a[i][j]=0;

}

}else{//如果一个点是白色的点,周围的点是黑色

nCount=0;

for(m=j-1;m<=j+1;m++){

for(n=i-1;n<=i+1;n++){

if(a[n][m]==1){

nCount++;

}

}

}

if(nCount>=blackThreshold){//周围黑点的个数大于阈值就变成黑色

a[i][j]=1;

}

}

}

}

}

找到极大全为1的矩形矩阵:

public static void findMaxBlackRect(){

int ans = 0;

//初始化

for(int i=1;i<=m;++i) {

l[0][i] = 1;

r[0][i] = m;

}

for(int i=1; i<=n; i++){

int maxl=1, maxr=m;

//计算h和l

for(int j=1; j<=m; j++){

if(a[i][j]==0){

h[i][j] = 0;

l[i][j] = 1;

maxl = j+1;

}else{

l[i][j] = Math.max(l[i-1][j],maxl);

h[i][j] = h[i-1][j]+1;

}

}

//计算r

for(int j=m; j>=1; j--){

if(a[i][j]==0){

r[i][j] = m;

maxr = j-1;

}else{

r[i][j] = Math.min(r[i-1][j],maxr);

int temp=ans;

ans = Math.max(ans,(r[i][j]-l[i][j]+1)*h[i][j]);

if(temp!=ans){

y1=l[i][j];

x1=i-h[i][j]+1;

rwidth=r[i][j]-l[i][j]+1;

rheight=h[i][j];

// System.out.println("i: "+i+" j:"+j+" l:"+l[i][j]+" r:"+r[i][j]+" h:"+h[i][j]);

}

}

}

}

//由于在二值化时将所有的点横纵坐标都加了1,找到矩形起点时要减去1

x1=x1-1;

y1=y1-1;

System.out.println("x1: "+x1+" y1: "+y1+" width: "+rwidth+" height: "+rheight);

}

粘贴图片:

public static void stickImage(String bigImagePath,String smallImagePath,String outImagePath) {

try {

BufferedImage bigImage = ImageIO.read(new File(bigImagePath));

BufferedImage smallImage = ImageIO.read(new File(smallImagePath));

Graphics2D gh=bigImage.createGraphics();

gh.drawImage(smallImage,null,x1,y1);

gh.dispose();

ImageIO.write(bigImage,"jpg",new File(outImagePath));

} catch (IOException ex) {

ex.printStackTrace();

}

}

没有输出路劲就随机产生一个:

public static void stickImage(String bigImagePath,String smallImagePath) {

try {

BufferedImage bigImage = ImageIO.read(new File(bigImagePath));

BufferedImage smallImage = ImageIO.read(new File(smallImagePath));

Graphics2D gh=bigImage.createGraphics();

gh.drawImage(smallImage,null,x1,y1);

gh.dispose();

ImageIO.write(bigImage,"jpg",new File(Generate.randomOutPutPath()));

} catch (IOException ex) {

ex.printStackTrace();

}

}

全文程序:

package com.edupt;

import javax.imageio.ImageIO;

import java.awt.*;

import java.awt.image.BufferedImage;

import java.io.File;

import java.io.IOException;

public class Calculate {

static int maxn = 2000;

static int n,m;

static int[][]a=new int[maxn][maxn]; //二值化结果

// static int[][]pixels;

static int[][]h=new int[maxn][maxn]; //高度

static int[][]l=new int[maxn][maxn];//向左能移动到的终点

static int[][]r=new int [maxn][maxn];//向右能移动到的终点

static int x1;

static int y1;

static int x2;

static int y2;

static int rwidth;

static int rheight;

static final int FZ=130;

public static void main(String[] args) {

String filePath="C:\\Users\\86130\\Desktop\\素材\\2019-12-30-17-56.jpg";

String filePath2="C:\\Users\\86130\\Desktop\\素材\\BigHead.jpg";

// String outPath="C:\\Users\\86130\\Desktop\\素材\\result1.jpg";

binaryImage(filePath,7);

// removeNoise(0,3);

print();

// findMaxBlackRect();

//stickImage(filePath,filePath2);

}

//二值化图像

public static void binaryImage(String filePath,double threshold){

try {

BufferedImage image = ImageIO.read(new File(filePath));

int minX = 0;//图片起始点X

int minY = 0;//图片起始点Y

int width = image.getWidth();//图片的宽度

m = width;

int height = image.getHeight();//图片的高度

n = height;

//pixels=new int[height][width];

//将黑色区域化为1,其他为0

for (int i = minX; i < width; i++) {

for (int j = minY; j < height; j++) {

Object data = image.getRaster().getDataElements(i, j, null);//获取该点像素,并以object类型表示

int red = image.getColorModel().getRed(data);

int blue = image.getColorModel().getBlue(data);

int green = image.getColorModel().getGreen(data);

if(red==0&&green==0&&blue==0){

a[i+1 ][j+1 ] = 1;

}

}

}

}catch (IOException e) {

e.printStackTrace();

}

}

/**

*

* @param whiteThreshold 默认为0

* @param blackThreshold

*/

public static void removeNoise(int whiteThreshold,int blackThreshold){

int i,j,nValue,nCount,m,n;

int nWidth=Calculate.maxn;

int nHeight=Calculate.maxn;

//对图像上下边缘去噪

for(i=0;i

a[i][0]=0;

a[i][nHeight-1]=0;

}

//对图像上下边缘去噪

for( i=0;i

a[0][i]=0;

a[0][nWidth-1]=0;

}

//根据周围点的颜色去噪

//遍历所有的点 //j是y, i是x

for(i=1;i

for( j=1;j

nValue=a[i][j];

if(nValue==1&&whiteThreshold!=0){//如果一点是黑点

nCount=0;

//遍历他周围的八个点,如果他

for(m=j-1;m<=j+1;m++){

for(n=i-1;n<=i+1;n++){

if(a[n][m]==0){//周围白点的个数

nCount++;

}

}

}

if(nCount>=whiteThreshold){//周围白点的个数大于阈值则变为白色

a[i][j]=0;

}

}else{//如果一个点是白色的点,周围的点是黑色

nCount=0;

for(m=j-1;m<=j+1;m++){

for(n=i-1;n<=i+1;n++){

if(a[n][m]==1){

nCount++;

}

}

}

if(nCount>=blackThreshold){//周围黑点的个数大于阈值就变成黑色

a[i][j]=1;

}

}

}

}

}

//找到极大全为1的矩形矩阵

public static void findMaxBlackRect(){

int ans = 0;

//初始化

for(int i=1;i<=m;++i) {

l[0][i] = 1;

r[0][i] = m;

}

for(int i=1; i<=n; i++){

int maxl=1, maxr=m;

//计算h和l

for(int j=1; j<=m; j++){

if(a[i][j]==0){

h[i][j] = 0;

l[i][j] = 1;

maxl = j+1;

}else{

l[i][j] = Math.max(l[i-1][j],maxl);

h[i][j] = h[i-1][j]+1;

}

}

//计算r

for(int j=m; j>=1; j--){

if(a[i][j]==0){

r[i][j] = m;

maxr = j-1;

}else{

r[i][j] = Math.min(r[i-1][j],maxr);

int temp=ans;

ans = Math.max(ans,(r[i][j]-l[i][j]+1)*h[i][j]);

if(temp!=ans){

y1=l[i][j];

x1=i-h[i][j]+1;

rwidth=r[i][j]-l[i][j]+1;

rheight=h[i][j];

// System.out.println("i: "+i+" j:"+j+" l:"+l[i][j]+" r:"+r[i][j]+" h:"+h[i][j]);

}

}

}

}

//由于在二值化时将所有的点横纵坐标都加了1,找到矩形起点时要减去1

x1=x1-1;

y1=y1-1;

System.out.println("x1: "+x1+" y1: "+y1+" width: "+rwidth+" height: "+rheight);

}

//粘贴图片

public static void stickImage(String bigImagePath,String smallImagePath,String outImagePath) {

try {

BufferedImage bigImage = ImageIO.read(new File(bigImagePath));

BufferedImage smallImage = ImageIO.read(new File(smallImagePath));

Graphics2D gh=bigImage.createGraphics();

gh.drawImage(smallImage,null,x1,y1);

gh.dispose();

ImageIO.write(bigImage,"jpg",new File(outImagePath));

} catch (IOException ex) {

ex.printStackTrace();

}

}

//没有输出路劲就随机产生一个

public static void stickImage(String bigImagePath,String smallImagePath) {

try {

BufferedImage bigImage = ImageIO.read(new File(bigImagePath));

BufferedImage smallImage = ImageIO.read(new File(smallImagePath));

Graphics2D gh=bigImage.createGraphics();

gh.drawImage(smallImage,null,x1,y1);

gh.dispose();

ImageIO.write(bigImage,"jpg",new File(Generate.randomOutPutPath()));

} catch (IOException ex) {

ex.printStackTrace();

}

}

public static void print(){

String filePath="C:\\Users\\86130\\Desktop\\素材\\2019-12-30-14-30.jpg";

try {

BufferedImage image=ImageIO.read(new File(filePath));

for(int i=501;i<=1000;i++){

for(int j=501;j<=1000;j++){

if(a[i][j]==0){

Object data = image.getRaster().getDataElements(i-1, j-1, null);//获取该点像素,并以object类型表示

int red = image.getColorModel().getRed(data);

int blue = image.getColorModel().getBlue(data);

int green = image.getColorModel().getGreen(data);

System.out.print("[ red "+red+" blue "+blue+" green "+green+" ]");

}

}

System.out.println();

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

java bufferedimage颜色_基于Java BufferedImage实现识别图片中的黑色矩形相关推荐

  1. java 托盘开发_基于java开发之系统托盘的应用

    代码如下: package com.b510.tray托盘; import java.awt.event.ActionEvent; import java.awt.event.ActionListen ...

  2. java path类_基于java Files类和Paths类的用法(详解)

    Java7中文件IO发生了很大的变化,专门引入了很多新的类: import java.nio.file.DirectoryStream; import java.nio.file.FileSystem ...

  3. java 实现违章_基于JAVA的车辆违章查询数据调用代码实例

    基于JAVA的车辆违章查询数据调用代码实例 代码描述:基于JA V A的车辆违章查询数据调用代码实例 相关平台:聚合数据 import java.io.BufferedReader; import j ...

  4. java消费者模式_基于Java 生产者消费者模式(详细分析)

    生产者消费者模式是多线程中最为常见的模式:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗.虽然它们任务不同,但处理的资源是相 ...

  5. java 酒店系统_基于JAVA的酒店管理系统

    <基于JAVA的酒店管理系统>由会员分享,可在线阅读,更多相关<基于JAVA的酒店管理系统(31页珍藏版)>请在人人文库网上搜索. 1.酒店管理系统,专业: 姓名: 指导教师, ...

  6. java订单类_基于Java创建一个订单类代码实例

    这篇文章主要介绍了基于Java创建一个订单类代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 需求描述 定义一个类,描述订单信息 订单id 订 ...

  7. java 雅思_基于JAVA的雅思考试管理系统的设计与实现(SSH,MySQL)(含录像)

    基于JAVA的雅思考试管理系统的设计与实现(SSH,MySQL)(含录像)(任务书,毕业论文12000字,程序代码,MySQL数据库) 本文分析了基于JAVA的雅思考试管理系统的设计与实现技术,结合实 ...

  8. java全文检索功能_基于Java的全文检索引擎简介

    Lucene是一个基于Java的全文索引工具包. 基于Java的全文索引引擎Lucene简介:关于作者和Lucene的历史 全文检索的实现:Luene全文索引和数据库索引的比较 中文切分词机制简介:基 ...

  9. java zip追加_基于Java向zip压缩包追加文件

    这篇文章主要介绍了基于Java向zip压缩包追加文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 有个需求,从某个接口下载的一个zip压缩包,往里 ...

最新文章

  1. 计算机表格计算总积分,Excel函数教程: 根据条件计算成绩表-excel技巧-电脑技巧收藏家...
  2. [转载] 七龙珠第一部——第092话 孙悟空上场了
  3. 投资狂人陈一舟:哪里火爆投哪里
  4. C#连接mysql数据库的一个例子和获取本机IP的方法
  5. C语言 字符串相关的函数
  6. Transformer详细解读与预测实例记录
  7. C# 虚方法与抽象方法区别
  8. 为什么Swift可能是深度学习的下一代重要的工具
  9. spring源码 学习方法
  10. Spark Streaming官网重点整理
  11. R语言—基本统计分析
  12. 重发布,路由策略实验
  13. 云文件共享服务器,云文件共享服务器软件
  14. python3和5_Python3算法之五:最大子序和
  15. 数字时钟单片机程序c语言,单片机数字时钟C语言程序
  16. 推荐阅读:太极拳的奥妙-专访七十肖维佳老翁现场展示
  17. matlab给图像加网格,matlab把图像进行网格化,或者是在图像中画网格
  18. Hibernate学习(七)
  19. php校园学校教室排课系统 php毕业设计题目课题选题 php毕业设计项目作品源码(3)任何老师和班主任功能
  20. Flink教程(10)- Flink批流一体API(其它)

热门文章

  1. mouseout、mouseover和mouseleave、mouseenter的区别
  2. Android Studio或Eclipse找不到逍遥安卓模拟器解决办法
  3. PostgreSQL 执行查询语句报错 ERROR: relation “table_xxx“ does not exist
  4. Arduino控制步进电机和舵机机器臂
  5. Mac 中批量修改文件编码格式
  6. 那些收入百万的NFT收藏者都做对了什么?
  7. 工作小记(二)----说说烦心事
  8. PyCharmMac键盘符
  9. 服务器防勒索病毒经验分享
  10. Android实现全屏图片的欢迎界面