/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package snailocr.util;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;

/**
 *
 * @author Administrator
 */
public class ImageTool {

private BufferedImage image;
    private int width;
    private int height;

/**
     * 变图像为黑白色 提示: 黑白化之前最好灰色化以便得到好的灰度平均值,利于获得好的黑白效果
     *
     * @return
     */
    public ImageTool changeToBlackWhiteImage() {
        int avgGrayValue = getAvgValue();
        int whitePoint = getWhitePoint(), blackPoint = getBlackPoint();

Color point;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                point = new Color(image.getRGB(j, i));
                image.setRGB(j, i, (point.getRed() < avgGrayValue ? blackPoint : whitePoint));
            }
        }
        return this;
    }

/**
     *
     *
     * @param whiteAreaPercent 过滤之后白色区域面积占整个图片面积的最小百分比
     * @param removeLighter true:过滤比中值颜色轻的,false:过滤比中值颜色重的,一般都是true
     * @return
     */
    public ImageTool midddleValueFilter(int whiteAreaMinPercent, boolean removeLighter) {
        int modify = 0;
        int avg = getAvgValue();
        Color point;
        while (getWhitePercent() < whiteAreaMinPercent) {
            for (int i = 0; i < height; i++) {
                for (int j = 0; j < width; j++) {
                    point = new Color(image.getRGB(j, i));
                    if (removeLighter) {
                        if (((point.getRed() + point.getGreen() + point.getBlue()) / 3) > avg - modify) {
//                         System.out.println(((point.getRed() + point.getGreen() + point.getBlue()) / 3)+"--"+(avg - modify));
                            image.setRGB(j, i, getWhitePoint());
                        }
                    } else {
                        if (((point.getRed() + point.getGreen() + point.getBlue()) / 3) < avg + modify) {
//                         System.out.println(((point.getRed() + point.getGreen() + point.getBlue()) / 3)+"--"+(avg - modify));
                            image.setRGB(j, i, getWhitePoint());
                        }
                    }

}
            }
            modify++;
        }
//        System.out.println(getWhitePercent());
        return this;
    }

private int getWhitePercent() {
        Color point;
        int white = 0;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                point = new Color(image.getRGB(j, i));
                if (((point.getRed() + point.getGreen() + point.getBlue()) / 3) == 255) {
                    white++;
                }
            }
        }
        return (int) Math.ceil(((float) white * 100 / (width * height)));
    }

/**
     * @param 变图像为灰色 取像素点的rgb三色平均值作为灰度值
     *
     * @return
     */
    public ImageTool changeToGrayImage() {
        int gray;
        Color point;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                point = new Color(image.getRGB(j, i));
                gray = (point.getRed() + point.getGreen() + point.getBlue()) / 3;
                image.setRGB(j, i, new Color(gray, gray, gray).getRGB());
            }
        }
        return this;
    }

/**
     *
     * 去除噪点和单点组成的干扰线 注意: 去除噪点之前应该对图像黑白化
     *
     * @param neighborhoodMinCount 每个点最少的邻居数
     * @return
     */
    public ImageTool removeBadBlock(int blockWidth, int blockHeight, int neighborhoodMinCount) {
        int val;
        int whitePoint = getWhitePoint();
        int counter, topLeftXIndex, topLeftYIndex;
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                //初始化邻居数为0
                counter = 0;
                topLeftXIndex = x - 1;
                topLeftYIndex = y - 1;
                //x1 y1是以x,y左上角点为顶点的矩形,该矩形包围在传入的矩形的外围,计算传入的矩形的有效邻居数目
                if (isBlackBlock(x, y, blockWidth, blockHeight)) {//只有当块是全黑色才计算
                    for (int x1 = topLeftXIndex; x1 <= topLeftXIndex + blockWidth + 1; x1++) {
                        for (int y1 = topLeftYIndex; y1 <= topLeftYIndex + blockHeight + 1; y1++) {
                            //判断这个点是否存在
                            if (x1 < width && x1 >= 0 && y1 < height && y1 >= 0) {
                                //判断这个点是否是传入矩形的外围点
                                if (x1 == topLeftXIndex || x1 == topLeftXIndex + blockWidth + 1
                                        || y1 == topLeftYIndex || y1 == topLeftYIndex + blockHeight + 1) {
                                    //这里假定图像已经被黑白化,取Red值认为不是0就是255
                                    val = new Color(image.getRGB(x1, y1)).getRed();
//                                System.out.println(val + "--" + (centerVal));
                                    //如果这个邻居是黑色,就把中心点的有效邻居数目加一
                                    if (val == 0) {
                                        counter++;
                                    }
                                }
                            }
                        }
                    }
//                    System.out.println("-------------------");
//                System.out.println(x+"-"+y+"-"+counter);
                    if (counter < neighborhoodMinCount) {
                        image.setRGB(x, y, whitePoint);
                    }
                }
            }
        }
        return this;
    }

/**
     * 如果点周围的黑点数达到补偿值就把这个点变为黑色
     *
     * @param addFlag 补偿阀值,通过观察处理过的图像确定,一般为2即可
     * @return
     */
    public ImageTool modifyBlank(int addFlag) {
        int val, counter = 0, topLeftXIndex, topLeftYIndex, blackPoint = getBlackPoint();
        Color point;
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                //初始化邻居数为0
                counter = 0;
                topLeftXIndex = x - 1;
                topLeftYIndex = y - 1;
                point = new Color(image.getRGB(x, y));
                //这里假定图像已经被黑白化,取Red值认为不是0就是255
                val = point.getRed();
                //只有白点才进行补偿
                if (val == 255) {
                    for (int x1 = topLeftXIndex; x1 <= topLeftXIndex + 2; x1++) {
                        for (int y1 = topLeftYIndex; y1 <= topLeftYIndex + 2; y1++) {
                            //判断这个点是否存在
                            if (x1 < width && x1 >= 0 && y1 < height && y1 >= 0) {
                                //判断这个点是否是传入点的外围点
                                if (x1 == topLeftXIndex || x1 == topLeftXIndex + 2
                                        || y1 == topLeftYIndex || y1 == topLeftYIndex + 2) {
                                    //这里假定图像已经被黑白化,取Red值认为不是0就是255
                                    val = new Color(image.getRGB(x1, y1)).getRed();
//                                System.out.println(val + "--" + (centerVal));
                                    //如果这个邻居是黑色,就把中心点的补偿数目加一
                                    if (val == 0) {
                                        counter++;
                                    }
                                }
                            }
                        }
                    }
                    //如果这个点周围的黑点数达到补偿值就把这个点变为黑色
                    if (counter >= addFlag) {
                        image.setRGB(x, y, blackPoint);
                    }
                }
            }
        }
        return this;
    }

public BufferedImage getBufferedImage(String filename) {
        File file = new File(filename);
        try {
            return ImageIO.read(file);
        } catch (IOException ex) {
            Logger.getLogger(ImageTool.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }

private boolean isBlackBlock(int startX, int startY, int blockWidth, int blockHeight) {
        int counter = 0;//统计黑色像素点的个数
        int total = 0;//统计有效像素点的个数
        int val;
        for (int x1 = startX; x1 <= startX + blockWidth - 1; x1++) {
            for (int y1 = startY; y1 <= startY + blockHeight - 1; y1++) {
                //判断这个点是否存在
                if (x1 < width && x1 >= 0 && y1 < height && y1 >= 0) {
                    total++;//有效像素点的个数
                    //这里假定图像已经被黑白化,取Red值认为不是0就是255
                    val = new Color(image.getRGB(x1, y1)).getRed();
                    //如果这个点是黑色,就把黑色像素点的数目加一
                    if (val == 0) {
                        counter++;
                    }
                }
            }
        }
//        System.out.println(startX + "--" + startY + "" + (counter == total&&total!=0));
        return counter == total && total != 0;
    }

private int getWhitePoint() {
        return (new Color(255, 255, 255).getRGB() & 0xffffffff);
    }

private int getBlackPoint() {
        return (new Color(0, 0, 0).getRGB() & 0xffffffff);
    }

private int getAvgValue() {
        Color point;
        int total = 0;
        for (int i = 0; i < height; i++) {
            for (int j = 0; j < width; j++) {
                point = new Color(image.getRGB(j, i));
                total += (point.getRed() + point.getGreen() + point.getBlue()) / 3;
            }
        }
        return total / (width * height);
    }

public void saveToFile(String filePath) {
        try {
            String ext = filePath.substring(filePath.lastIndexOf(".") + 1);
            File newFile = new File(filePath);
            ImageIO.write(image, ext, newFile);
        } catch (IOException ex) {
            Logger.getLogger(ImageTool.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

public BufferedImage getImage() {
        return image;
    }

public void setImage(BufferedImage image) {
        this.image = image;
        width = image.getWidth();
        height = image.getHeight();
    }
}

java 验证码图片处理类,为验证码识别做准备的更多相关文章

  1. c# 验证码图片生成类

    using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D ...

  2. ThinkPHP---TP功能类之验证码

    [一]验证码 验证码全称:captcha(全自动识别机器与人类的图灵测试),简单理解就是区分当前操作是人执行的还是机器执行的 常见验证码分3种:页面上图片形式.短信验证码(邮箱验证可以归类到短信验证码 ...

  3. Java中SSM+Shiro系统登录验证码的实现方法

    1.验证码生成类: import java.util.Random; import java.awt.image.BufferedImage; import java.awt.Graphics; im ...

  4. .Net中验证码图片生成

    开发网站或平台系统,登录页面是必不可少的功能,但是现在很多人可以使用工具暴力破解网站密码,为了防止这类非法操作,需要在登录页面添加验证,验证码就是最常用的一种验证方式. 我结合了自己的经验和网上的验证 ...

  5. Winform中产生验证码图片

    1.创建ValidCode类: public class ValidCode { #region Private Fields private const double PI = 3.14159265 ...

  6. 验证码在后台的编写,并实现点击验证码图片时时发生更新 C# 项目发布到IIS后不能用log4net写日志

    验证码在后台的编写,并实现点击验证码图片时时发生更新   验证码在软件中的地位越来越重要,有效防止这种问题对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试:下面就是实现验证码的基本步骤: ...

  7. asp.net验证码图片生成示例

    验证码,一个很常见的东西.不管你是使用者还是开发者,这个东西80%的人都见到过,但是之前有人给我说过这么一句话“内行看门道,外行看热闹!”,仔细琢磨一下还真的是那么一回事.对于怎么实现验证码,闲话不多 ...

  8. 验证码图片生成工具类——Captcha.java

    验证码图片生成工具,使用JAVA生成的图片验证码,调用getRandcode方法获取图片验证码,以流的方式传输到前端页面. 源码如下:(点击下载  Captcha.java) import java. ...

  9. java生成图片验证码(转)--封装生成图片验证码的工具类

    博客部分内容转载自 LonlySnow的博客:后台java 实现验证码生成 1.controller方法 @RequestMapping(value = "/verifycode/img&q ...

随机推荐

  1. Python的pep8(代码规范)

    Python的pep8-代码规范 1.    代码布局设计 1.1    缩进 A.   使用四个空格来进行缩进 B.   换行的时候可以使用反斜杠,最好的方法是使用园括号,在使用反斜杠的时候,在反斜 ...

  2. 【LeetCode】70 - Climbing Stairs

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...

  3. 判断是否为BST

    递归的方法,用返回false的方法.中序遍历的想法很好,空间浪费.遍历的过程记录上一次的值进行比较. //题目描述 // //请实现一个函数,检查一棵二叉树是否为二叉查找树. //给定树的根结点指针T ...

  4. offer--链表反转和从尾到头打印链表

    这个是高频的面试题,今天总结了一些.反转链表用三个指针实现,返回新链表的头节点:而从尾到头打印,应用栈实现,返回vector整个链表. //题目描述 // //输入一个链表,反转链表后,输出链表的所有 ...

  5. Linux下的GitHub安装与简单配置教程

    1.GitHub简介 Git是一个分布式版本控制系统,与其相对的是CVS.SVN等集中式的版本控制系统. 2.Git的安装 1)安装Git a.查看与使用 在ubuntu下可以使用如下命令进行查看系统 ...

  6. 使用Go开发一个简单的服务器程序

    最近有个小项目,需要一个简单的后台程序来支撑,本来想用Nodejs来做,但是由于本人js一直很菜,并且很讨厌callback,虽然我也很喜欢异步模型,但我一直都觉得JS是反人类的.后台就用了go处理, ...

  7. 转】启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099的解决办法

    原博文出自于:http://www.cnblogs.com/xdp-gacl/p/5288399.html   感谢! 一.问题描述 今天一来公司,在IntelliJ IDEA 中启动Tomcat服务 ...

  8. angular的directive笔记

    原贴地址 1,tansclude: 是指令能够能够把外部定义的内容传回指令模板内部(通过在内部标签使用ng-transclude).这个外部指定的内容是根据外部的作用域控制的,跟指令的作用域无关.这个 ...

  9. 安装CiscoWorks LMS

    安装CiscoWorks LMS,需要安装5张光盘,CiscoWorks LMS的安装步骤比较简单,在这里只介绍需要的重要步骤. 1.安装CD One 将CiscoWorks 2000 LMS CD ...

  10. POJ3253Fence Repair(优先队列或单调队列)

    http://poj.org/problem?id=3253 经典题目了,大意是说如果要切断一个长度为a的木条需要花费代价a, 问要切出要求的n个木条所需的最小代价. 无论是以下哪种方法,最原始的思路 ...