JAVA识别复杂验证码+图像处理

先对验证码进行简单的处理噪点和纯色

例未曾处理的图片

public static void main(String[] args) throws Exception {
   //源文件
  String picName = "C:\\Users\\syxy101\\Desktop\\6.jpg";

 File filepic=new File(picName);
//去噪点 并处理为纯色
  BufferedImage bufferedImage = removeBackgroud(picName);
//处理后图片地址
File w2 = new File("C:\\Users\\syxy101\\Desktop\\5.png");//可以是jpg,png格式
ImageIO.write(bufferedImage, "jpg", w2);//不管输出什么格式图片,此处不需改动


//去除图片噪点  并将彩色转为纯色(黑色)
  public static BufferedImage removeBackgroud(String picFile)
            throws Exception {
        BufferedImage img = ImageIO.read(new File(picFile));
        int width = img.getWidth();
        int height = img.getHeight();
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                if (isWhite(img.getRGB(x, y)) == 1) {
                    img.setRGB(x, y, Color.WHITE.getRGB());
                } else {
                    img.setRGB(x, y, Color.BLACK.getRGB());
                }
            }
        }
        return img;
    }
//设置颜色阀值
 public static int isWhite(int colorInt) {
        Color color = new Color(colorInt);
        if (color.getRed() + color.getGreen() + color.getBlue() > 200 && color.getRed() + color.getGreen() + color.getBlue()<500) {
            return 0;
        }
        return 1;
    }
处理后

可以看到已经清晰了不少  当然现在还是无法识别的

一下步 强加黑色 处理掉横线斜线 噪点

package com.adc.da.sync.web;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.io.IOUtils;

import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * //TODO 添加类/接口功能描述
 *
 * @author zhangsj
 * @date 2018-12-13
 */
public class ImagePreProcess4 {

        public static void main(String[] args) throws IOException
        {
            //源文件
            File testDataDir = new File("C:\\Users\\syxy101\\Desktop\\5.png");
            //处理后路径
            final String destDir = "C:\\Users\\syxy101\\Desktop\\ss";
                cleanLinesInImage(testDataDir, destDir);
        }

        /**
         *
         * @param sfile
         *            需要去噪的图像
         * @param destDir
         *            去噪后的图像保存地址
         * @throws IOException
         */
        public static void cleanLinesInImage(File sfile, String destDir)  throws IOException{
            File destF = new File(destDir);
            if (!destF.exists())
            {
                destF.mkdirs();
            }

            BufferedImage bufferedImage = ImageIO.read(sfile);
            int h = bufferedImage.getHeight();
            int w = bufferedImage.getWidth();

            // 灰度化
            int[][] gray = new int[w][h];
            for (int x = 0; x < w; x++)
            {
                for (int y = 0; y < h; y++)
                {
                    int argb = bufferedImage.getRGB(x, y);
                    // 图像加亮(调整亮度识别率非常高)
                    int r = (int) (((argb >> 16) & 0xFF) * 1.1 + 30);
                    int g = (int) (((argb >> 8) & 0xFF) * 1.1 + 30);
                    int b = (int) (((argb >> 0) & 0xFF) * 1.1 + 30);
                    if (r >= 255)
                    {
                        r = 255;
                    }
                    if (g >= 255)
                    {
                        g = 255;
                    }
                    if (b >= 255)
                    {
                        b = 255;
                    }
                    gray[x][y] = (int) Math
                            .pow((Math.pow(r, 2.2) * 0.2973 + Math.pow(g, 2.2)
                                    * 0.6274 + Math.pow(b, 2.2) * 0.0753), 1 / 2.2);
                }
            }

            // 二值化
            int threshold = ostu(gray, w, h);
            BufferedImage binaryBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
            for (int x = 0; x < w; x++)
            {
                for (int y = 0; y < h; y++)
                {
                    if (gray[x][y] > threshold)
                    {
                        gray[x][y] |= 0x00FFFF;
                    } else
                    {
                        gray[x][y] &= 0xFF0000;
                    }
                    binaryBufferedImage.setRGB(x, y, gray[x][y]);
                }
            }

            //去除干扰线条
            for(int y = 1; y < h-1; y++){
                for(int x = 1; x < w-1; x++){
                    boolean flag = false ;
                    if(isBlack(binaryBufferedImage.getRGB(x, y))){
                        //左右均为空时,去掉此点
                        if(isWhite(binaryBufferedImage.getRGB(x-1, y)) && isWhite(binaryBufferedImage.getRGB(x+1, y))){
                            flag = true;
                        }
                        //上下均为空时,去掉此点
                        if(isWhite(binaryBufferedImage.getRGB(x, y+1)) && isWhite(binaryBufferedImage.getRGB(x, y-1))){
                            flag = true;
                        }
                        //斜上下为空时,去掉此点
                        if(isWhite(binaryBufferedImage.getRGB(x-1, y+1)) && isWhite(binaryBufferedImage.getRGB(x+1, y-1))){
                            flag = true;
                        }
                        if(isWhite(binaryBufferedImage.getRGB(x+1, y+1)) && isWhite(binaryBufferedImage.getRGB(x-1, y-1))){
                            flag = true;
                        }
                        if(flag){
                            binaryBufferedImage.setRGB(x,y,-1);
                        }
                    }
                }
            }


            // 矩阵打印
            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    if (isBlack(binaryBufferedImage.getRGB(x, y)))
                    {
                        System.out.print("*");
                    } else
                    {
                        System.out.print(" ");
                    }
                }
                System.out.println();
            }

            ImageIO.write(binaryBufferedImage, "jpg", new File(destDir, sfile
                    .getName()));
        }

        public static boolean isBlack(int colorInt)
        {
            Color color = new Color(colorInt);
            if (color.getRed() + color.getGreen() + color.getBlue() <= 300)
            {
                return true;
            }
            return false;
        }

        public static boolean isWhite(int colorInt)
        {
            Color color = new Color(colorInt);
            if (color.getRed() + color.getGreen() + color.getBlue() > 300)
            {
                return true;
            }
            return false;
        }

        public static int isBlackOrWhite(int colorInt)
        {
            if (getColorBright(colorInt) < 30 || getColorBright(colorInt) > 730)
            {
                return 1;
            }
            return 0;
        }

        public static int getColorBright(int colorInt)
        {
            Color color = new Color(colorInt);
            return color.getRed() + color.getGreen() + color.getBlue();
        }

        public static int ostu(int[][] gray, int w, int h)
        {
            int[] histData = new int[w * h];
            // Calculate histogram
            for (int x = 0; x < w; x++)
            {
                for (int y = 0; y < h; y++)
                {
                    int red = 0xFF & gray[x][y];
                    histData[red]++;
                }
            }

            // Total number of pixels
            int total = w * h;

            float sum = 0;
            for (int t = 0; t < 256; t++)
                sum += t * histData[t];

            float sumB = 0;
            int wB = 0;
            int wF = 0;

            float varMax = 0;
            int threshold = 0;

            for (int t = 0; t < 256; t++)
            {
                wB += histData[t]; // Weight Background
                if (wB == 0)
                    continue;

                wF = total - wB; // Weight Foreground
                if (wF == 0)
                    break;

                sumB += (float) (t * histData[t]);

                float mB = sumB / wB; // Mean Background
                float mF = (sum - sumB) / wF; // Mean Foreground

                // Calculate Between Class Variance
                float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);

                // Check if new maximum found
                if (varBetween > varMax)
                {
                    varMax = varBetween;
                    threshold = t;
                }
            }

            return threshold;
        }
    }

已经去掉多余的横线和噪点了 

这时候识别度已经很高了 

为了达到识别度百分之80

需要把每个字母隔开 分开识别

  public static void main(String[] args) throws Exception {

   int x=6;
      for(int i=0;i<4;i++){
            if(i==0){
                x=6;
            }else if(i==1){
                x=22;
            }else if(i==2){
                x=36;
            }else if(i==3){
                x=52;
            }
            imageCut(x,0,15,30,picName,"D:\\ccccc"+i+".jpg");

        }


   /**
     * 图片剪裁
     * @param x 距离左上角的x轴距离
     * @param y 距离左上角的y轴距离
     * @param width 宽度
     * @param height 高度
     * @param sourcePath 图片源
     * @param descpath 目标位置
     */
    public static void imageCut(int x, int y, int width, int height, String sourcePath, String descpath) {
        FileInputStream is = null;
        ImageInputStream iis = null;
        try {
            is = new FileInputStream(sourcePath);
            String fileSuffix = sourcePath.substring(sourcePath.lastIndexOf(".") + 1);
            Iterator<ImageReader> it = ImageIO.getImageReadersByFormatName(fileSuffix);
            ImageReader reader = it.next();
            iis = ImageIO.createImageInputStream(is);
            reader.setInput(iis, true);
            ImageReadParam param = reader.getDefaultReadParam();
            Rectangle rect = new Rectangle(x, y, width, height);
            param.setSourceRegion(rect);
            BufferedImage bi = reader.read(0, param);
            ImageIO.write(bi, fileSuffix, new File(descpath));
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                is = null;
            }
            if (iis != null) {
                try {
                    iis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                iis = null;
            }
        }
    }
 

换了个验证码剪辑

这时候识别度已经到百分之90了

后期整理一个识别字符的工具
--------------------- 
作者:随波逐流baby 
来源:CSDN 
原文:https://blog.csdn.net/qq_34351177/article/details/84992133 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/weixin_41508948/article/details/91960255