cn.z.Ocr5.java Source code

Java tutorial

Introduction

Here is the source code for cn.z.Ocr5.java

Source

/*
 * Copyright (C) 2016. The CloudKit Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.z;

import cn.z.svm.svm_predict;
import cn.z.svm.svm_train;
import cn.z.util.CommonUtil;
import com.jhlabs.image.ScaleFilter;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
import org.apache.commons.io.IOUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Ocr5 {

    private static String clazz = Ocr5.class.getSimpleName();
    private static Map<BufferedImage, String> trainMap = null;
    private static int whiteThreshold = 600;
    private static boolean useSvm = true;

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

    public static int isBlack(int colorInt, int blackThreshold) {
        final Color color = new Color(colorInt);
        if (color.getRed() + color.getGreen() + color.getBlue() <= blackThreshold) {
            return 1;
        }
        return 0;
    }

    public static int isWhite(int colorInt, int whiteThreshold) {
        final Color color = new Color(colorInt);
        if (color.getRed() + color.getGreen() + color.getBlue() > whiteThreshold) {
            return 1;
        }
        return 0;
    }

    public static BufferedImage removeBackgroud(File picFile) throws Exception {

        BufferedImage img = ImageIO.read(picFile);
        final int width = img.getWidth();
        final int height = img.getHeight();

        // int blackThreshold = 300;

        // img.getMinX() img.getMinY()
        for (int x = img.getMinX(); x < width; x++) {
            for (int y = img.getMinY(); y < height; y++) {

                Color color = new Color(img.getRGB(x, y));
                if ((color.getBlue() < 120) || ((color.getRed() + color.getGreen() + color.getBlue()) < 50)) { //
                    img.setRGB(x, y, Color.WHITE.getRGB());
                } else if ((color.getRed() + color.getGreen() + color.getBlue()) < 400) {
                    img.setRGB(x, y, Color.BLACK.getRGB());
                }

                int nearly = 0;
                int vertical = 0;
                int horizontal = 0;

                if (x > 0) {
                    Color leftColor = new Color(img.getRGB(x - 1, y));
                    if ((leftColor.getRed() + leftColor.getGreen() + leftColor.getBlue()) < 400) {
                        nearly++;
                        horizontal++;
                    }
                }
                if (x < width - 1) {
                    Color rightColor = new Color(img.getRGB(x + 1, y));
                    if ((rightColor.getRed() + rightColor.getGreen() + rightColor.getBlue()) < 400) {
                        nearly++;
                        horizontal++;
                    }
                }
                if (y > 0) {
                    Color topColor = new Color(img.getRGB(x, y - 1));
                    if ((topColor.getRed() + topColor.getGreen() + topColor.getBlue()) < 400) {
                        nearly++;
                        vertical++;
                    }
                }
                if (y < height - 1) {
                    Color bottomColor = new Color(img.getRGB(x, y + 1));
                    if ((bottomColor.getRed() + bottomColor.getGreen() + bottomColor.getBlue()) < 400) {
                        nearly++;
                        vertical++;
                    }
                }

                if (x > 0 && y > 0) {
                    Color leftTopColor = new Color(img.getRGB(x - 1, y - 1));
                    if ((leftTopColor.getRed() + leftTopColor.getGreen() + leftTopColor.getBlue()) < 400) {
                        nearly++;
                    }
                }
                if (x < width - 1 && y < height - 1) {
                    Color rightBottomColor = new Color(img.getRGB(x + 1, y + 1));
                    if ((rightBottomColor.getRed() + rightBottomColor.getGreen()
                            + rightBottomColor.getBlue()) < 400) {
                        nearly++;
                    }
                }
                if (x < width - 1 && y > 0) {
                    Color rightTopColor = new Color(img.getRGB(x + 1, y - 1));
                    if ((rightTopColor.getRed() + rightTopColor.getGreen() + rightTopColor.getBlue()) < 400) {
                        nearly++;
                    }
                }
                if (x > 0 && y < height - 1) {
                    Color leftBottomColor = new Color(img.getRGB(x - 1, y + 1));
                    if ((leftBottomColor.getRed() + leftBottomColor.getGreen() + leftBottomColor.getBlue()) < 400) {
                        nearly++;
                    }
                }

                if (nearly < 2) {
                    img.setRGB(x, y, Color.WHITE.getRGB());
                }
                /*
                if (horizontal < 1 && vertical > 0) {
                img.setRGB(x, y, Color.WHITE.getRGB());
                }
                if (horizontal > 0 && vertical < 1) {
                img.setRGB(x, y, Color.WHITE.getRGB());
                }
                */

                /*
                if (isWhite(img.getRGB(x, y), whiteThreshold) == 1) {
                img.setRGB(x, y, Color.WHITE.getRGB());
                } else {
                img.setRGB(x, y, Color.BLACK.getRGB());
                }
                    
                    
                if (getColorBright(img.getRGB(x, y)) < 100) {
                int count = isBlack(img.getRGB(x - 1, y), blackThreshold) + isBlack(img.getRGB(x + 1, y), blackThreshold) + isBlack(img.getRGB(x, y - 1), blackThreshold) + isBlack(img.getRGB(x, y + 1), blackThreshold) + isBlack(img.getRGB(x + 1, y + 1), blackThreshold) + isBlack(img.getRGB(x - 1, y - 1), blackThreshold) + isBlack(img.getRGB(x + 1, y -1 ), blackThreshold) + isBlack(img.getRGB(x - 1, y + 1), blackThreshold);
                System.out.println(count);
                if (count < 2) {
                    img.setRGB(x, y, Color.WHITE.getRGB());
                }
                //     img.setRGB(x, y, Color.WHITE.getRGB());
                }
                */

                //                if(getColorBright(img.getRGB(x, y)) > 600) {
                //                    img.setRGB(x, y, Color.WHITE.getRGB());
                //                } else {
                //                    /*
                //                    // ?Graphics2D
                //                    Graphics2D g2d = img.createGraphics();
                //                    // ?
                //                    // 1.0f? 0-1.0????
                //                    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1.0f));
                //                    // 
                //                    g2d.setColor(new Color(255,0,0));
                //                    g2d.setStroke(new BasicStroke(1));
                //                    // g2d.draw
                //                    // 
                //                    // ? ?
                //                    g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
                //                    g2d.dispose();
                //                    */
                //
                //                    img.setRGB(x, y, Color.BLACK.getRGB());
                //                    /*
                //                    System.out.println(getColorBright(img.getRGB(x, y)) + ":");
                //                    System.out.println(getColorBright(img.getRGB(x + 1, y)) + "-" + getColorBright(img.getRGB(x + 1, y + 1)) + "-" + getColorBright(img.getRGB(x, y + 1)));
                //                    System.out.println(getColorBright(img.getRGB(x - 1, y)) + "-" + getColorBright(img.getRGB(x - 1, y - 1)) + "-" + getColorBright(img.getRGB(x, y - 1)));
                //                    System.out.println(getColorBright(img.getRGB(x - 1, y + 1)) + "-" + getColorBright(img.getRGB(x + 1, y - 1)));
                //                    */
                //
                //                    /*
                //                    int i = 0;
                //                    i = ((x < width - 1) && getColorBright(img.getRGB(x + 1, y)) < 30)? i + 1 : i;
                //                    i = ((x < width - 1) && (y < height - 1) && getColorBright(img.getRGB(x + 1, y + 1)) < 30)? i + 1 : i;
                //                    i = ((y < height - 1) && getColorBright(img.getRGB(x, y + 1)) < 30)? i + 1 : i;
                //                    i = ((x > 0) && getColorBright(img.getRGB(x - 1, y)) < 30)? i + 1 : i;
                //                    i = ((x > 0) && (y > 0) && getColorBright(img.getRGB(x - 1, y - 1)) < 30)? i + 1 : i;
                //                    i = ((y > 0) && getColorBright(img.getRGB(x, y - 1)) < 30)? i + 1 : i;
                //                    i = ((x < width - 1) && (y > 0) && getColorBright(img.getRGB(x + 1, y - 1)) < 30)? i + 1 : i;
                //                    i = ((x > 0) && (y < height - 1) && getColorBright(img.getRGB(x - 1, y + 1)) < 30)? i + 1 : i;
                //
                //                    if(i > 1) {
                //                        img.setRGB(x, y, Color.BLACK.getRGB());
                //                    } else {
                //                        img.setRGB(x, y, Color.WHITE.getRGB());
                //                    }
                //                    */
                //                }

                /*
                int i = 0;
                i = (getColorBright(img.getRGB(x + 1, y)) == 0)? i + 1 : i;
                i = (getColorBright(img.getRGB(x + 1, y + 1)) == 0)? i + 1 : i;
                i = (getColorBright(img.getRGB(x, y + 1)) == 0)? i + 1 : i;
                i = (getColorBright(img.getRGB(x - 1, y)) == 0)? i + 1 : i;
                i = (getColorBright(img.getRGB(x - 1, y - 1)) == 0)? i + 1 : i;
                i = (getColorBright(img.getRGB(x, y - 1)) == 0)? i + 1 : i;
                    
                System.out.println(getColorBright(img.getRGB(x, y)) + ":");
                System.out.println(getColorBright(img.getRGB(x + 1, y)) + "-" + getColorBright(img.getRGB(x + 1, y + 1)) + "-" + getColorBright(img.getRGB(x, y + 1)));
                System.out.println(getColorBright(img.getRGB(x - 1, y)) + "-" + getColorBright(img.getRGB(x - 1, y - 1)) + "-" + getColorBright(img.getRGB(x, y - 1)));
                System.out.println(getColorBright(img.getRGB(x - 1, y + 1)) + "-" + getColorBright(img.getRGB(x + 1, y - 1)));
                if(getColorBright(img.getRGB(x, y)) == 0 &&  i < 3) {
                img.setRGB(x, y, Color.WHITE.getRGB());
                }
                */

                /*
                // ?for????
                // ??object
                Object data = img.getRaster().getDataElements(x, y, null);
                int red = img.getColorModel().getRed(data);
                int blue = img.getColorModel().getBlue(data);
                int green = img.getColorModel().getGreen(data);
                System.out.println((red + blue + green) + "-" + getColorBright(img.getRGB(x, y)));
                red = (red * 3 + green * 6 + blue * 1)/10;
                green = red;
                blue = green;
                    
                // r?g?b?rgbbufferedImage????rgbrgb8388608?255*255*255?16777216
                int rgb = (red * 256 + green) * 256 + blue;
                if(rgb > 8388608) {
                rgb = rgb - 16777216;
                }
                // rgb
                img.setRGB(x, y, rgb);
                */

            }
        }
        // img = img.getSubimage(1, 1, img.getWidth() - 2, img.getHeight() - 2);
        return img;
    }

    /*
    private static List<BufferedImage> splitImage(BufferedImage img, String filename) throws Exception {
    final List<BufferedImage> subImgs = new ArrayList<BufferedImage>();
    subImgs.add(img.getSubimage(0, 0, 16, 25));
    subImgs.add(img.getSubimage(16, 0, 16, 25));
    subImgs.add(img.getSubimage(32, 0, 16, 25));
    subImgs.add(img.getSubimage(48, 0, 16, 25));
        
    //        // TODO
    //        for(int i = 0; i < subImgs.size(); i++) {
    //            FileOutputStream fos = new FileOutputStream("D:\\test\\img" + filename + i + ".jpg");
    //            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
    //            encoder.encode(subImgs.get(i));
    //            fos.close();
    //        }
    return subImgs;
    }
    */

    public static List<BufferedImage> splitImage(BufferedImage img, String filename) throws Exception {
        final List<BufferedImage> subImgs = new ArrayList<BufferedImage>();
        final int width = img.getWidth();
        final int height = img.getHeight();
        final List<Integer> weightlist = new ArrayList<Integer>();
        for (int x = 0; x < width; ++x) {
            int count = 0;
            for (int y = 0; y < height; ++y) {
                if (CommonUtil.isWhite(img.getRGB(x, y), whiteThreshold) == 0) {
                    count++;
                }
            }
            weightlist.add(count);
        }
        for (int i = 0; i < weightlist.size(); i++) {
            int length = 0;
            while (i < weightlist.size() && weightlist.get(i) > 0) {
                i++;
                length++;
            }
            if (length > 18) {
                subImgs.add(CommonUtil.removeBlank(img.getSubimage(i - length, 0, length / 2, height),
                        whiteThreshold, 0));
                subImgs.add(CommonUtil.removeBlank(img.getSubimage(i - length / 2, 0, length / 2, height),
                        whiteThreshold, 0));
            } else if (length > 5) {
                subImgs.add(
                        CommonUtil.removeBlank(img.getSubimage(i - length, 0, length, height), whiteThreshold, 0));
            }
        }

        //        for(int i = 0; i < subImgs.size(); i++) {
        //            FileOutputStream fos = new FileOutputStream("D:\\test\\img" + filename + i + ".jpg");
        //            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
        //            encoder.encode(subImgs.get(i));
        //            fos.close();
        //        }
        return subImgs;
    }

    public static boolean isNotEight(BufferedImage img) {
        final int width = img.getWidth();
        final int height = img.getHeight();
        int minCount = width;
        for (int y = height / 2 - 2; y < height / 2 + 2; ++y) {
            int count = 0;
            for (int x = 0; x < width / 2 + 2; ++x) {
                if (CommonUtil.isWhite(img.getRGB(x, y), whiteThreshold) == 0) {
                    count++;
                }
            }
            minCount = Math.min(count, minCount);
        }
        return minCount < 2;
    }

    public static boolean isNotThree(BufferedImage img) {
        final int width = img.getWidth();
        final int height = img.getHeight();
        int minCount = width;
        for (int y = height / 2 - 3; y < height / 2 + 3; ++y) {
            int count = 0;
            for (int x = 0; x < width / 2 + 1; ++x) {
                if (CommonUtil.isWhite(img.getRGB(x, y), whiteThreshold) == 0) {
                    count++;
                }
            }
            minCount = Math.min(count, minCount);
        }
        return minCount > 0;
    }

    public static boolean isNotFive(BufferedImage img) {
        final int width = img.getWidth();
        final int height = img.getHeight();
        int minCount = width;
        for (int y = 0; y < height / 3; ++y) {
            int count = 0;
            for (int x = width * 2 / 3; x < width; ++x) {
                if (CommonUtil.isWhite(img.getRGB(x, y), whiteThreshold) == 0) {
                    count++;
                }
            }
            minCount = Math.min(count, minCount);
        }
        return minCount > 0;
    }

    public static String getSingleCharOcr(BufferedImage img, Map<BufferedImage, String> map) throws Exception {
        if (useSvm) {
            final String input = new File("img/" + clazz + "/input.txt").getAbsolutePath();
            final String output = new File("result/" + clazz + "/output.txt").getAbsolutePath();
            CommonUtil.imgToSvmInput(img, input, whiteThreshold);
            svm_predict.main(new String[] { input, new File("train/" + clazz + "/data.txt.model").getAbsolutePath(),
                    output });
            final List<String> predict = IOUtils.readLines(new FileInputStream(output));
            if (predict.size() > 0 && predict.get(0).length() > 0) {
                return predict.get(0).substring(0, 1);
            }
            return "#";
        }

        String result = "#";
        img = scaleImage(img);
        final int width = img.getWidth();
        final int height = img.getHeight();
        int min = width * height;
        final boolean bNotEight = isNotEight(img);
        final boolean bNotThree = isNotThree(img);
        final boolean bNotFive = isNotFive(img);
        for (final BufferedImage bi : map.keySet()) {
            if (bNotThree && map.get(bi).startsWith("3")) {
                continue;
            }
            if (bNotEight && map.get(bi).startsWith("8")) {
                continue;
            }
            if (bNotFive && map.get(bi).startsWith("5")) {
                continue;
            }
            final double count1 = getBlackCount(img);
            final double count2 = getBlackCount(bi);
            if (Math.abs(count1 - count2) / Math.max(count1, count2) > 0.25) {
                continue;
            }
            int count = 0;
            if (width < bi.getWidth() && height < bi.getHeight()) {
                for (int m = 0; m <= bi.getWidth() - width; m++) {
                    for (int n = 0; n <= bi.getHeight() - height; n++) {
                        Label1: for (int x = m; x < m + width; ++x) {
                            for (int y = n; y < n + height; ++y) {
                                if (CommonUtil.isWhite(img.getRGB(x - m, y - n), whiteThreshold) != CommonUtil
                                        .isWhite(bi.getRGB(x, y), whiteThreshold)) {
                                    count++;
                                    if (count >= min) {
                                        break Label1;
                                    }
                                }
                            }
                        }
                    }
                }
            } else {
                final int widthmin = width < bi.getWidth() ? width : bi.getWidth();
                final int heightmin = height < bi.getHeight() ? height : bi.getHeight();
                Label1: for (int x = 0; x < widthmin; ++x) {
                    for (int y = 0; y < heightmin; ++y) {
                        if (CommonUtil.isWhite(img.getRGB(x, y), whiteThreshold) != CommonUtil
                                .isWhite(bi.getRGB(x, y), whiteThreshold)) {
                            count++;
                            if (count >= min) {
                                break Label1;
                            }
                        }
                    }
                }
            }
            if (count < min) {
                min = count;
                result = map.get(bi);
            }
        }
        return result;
    }

    public static String getAllOcr(File file, String filename) throws Exception {
        final BufferedImage img = removeBackgroud(file);
        // BufferedImage img = ImageIO.read(file);
        /*
        // TODO
        FileOutputStream fos = new FileOutputStream("D:\\img.jpg");
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(fos);
        encoder.encode(img);
        fos.close();
        */

        final List<BufferedImage> listImg = splitImage(img, filename);
        final Map<BufferedImage, String> map = loadTrainData();
        String result = useSvm ? "svm_" : "";
        for (final BufferedImage bi : listImg) {
            result += getSingleCharOcr(bi, map);
        }
        System.out.println(result);
        ImageIO.write(img, "JPG", new File("result/" + clazz + "/" + result + ".jpg"));
        return result;
    }

    public static Map<BufferedImage, String> loadTrainData() throws Exception {
        if (trainMap == null) {
            final Map<BufferedImage, String> map = new HashMap<BufferedImage, String>();
            final File dir = new File("train/" + clazz);
            final File[] files = dir.listFiles(new FilenameFilter() {
                @Override
                public boolean accept(File dir, String name) {
                    return name.toLowerCase().endsWith(".jpg");
                }
            });
            for (final File file : files) {
                map.put(scaleImage(ImageIO.read(file)), file.getName().charAt(0) + "");
            }
            trainMap = map;
        }
        return trainMap;
    }

    public static int getBlackCount(BufferedImage img) {
        final int width = img.getWidth();
        final int height = img.getHeight();
        int count = 0;
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                if (CommonUtil.isWhite(img.getRGB(x, y), whiteThreshold) == 0) {
                    count++;
                }
            }
        }
        return count;
    }

    public static BufferedImage scaleImage(BufferedImage img) {
        final ScaleFilter sf = new ScaleFilter(16, 16);
        final BufferedImage imgdest = new BufferedImage(16, 16, img.getType());
        return sf.filter(img, imgdest);
    }

    public static void main(String[] args) throws Exception {
        // ---step1 downloadImage
        // String url = "http://reg.keepc.com/getcode/getCode.php";
        // 
        // CommonUtil.downloadImage(url, clazz);
        File file = new File("img/" + clazz);
        if (!file.exists()) {
            file.mkdirs();
        }
        new File("train/" + clazz).mkdirs();
        new File("result/" + clazz).mkdirs();

        File[] files = file.listFiles();
        // result/ocr
        for (int i = 0; i < files.length; ++i) {
            final String text = getAllOcr(files[i], files[i].getName());
            System.out.println(i + ".jpg = " + text);
        }

        //         CommonUtil.scaleTraindata(clazz, whiteThreshold);
        //         svm_train train = new svm_train();
        //         train.run(new String[] { new File("train/" + clazz + "/data.txt").getAbsolutePath(), new File("train/" + clazz + "/data.txt.model").getAbsolutePath() });
    }

}