欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java使用Tessdata做OCR圖片文字識別的詳細思路

 更新時間:2021年07月29日 16:58:45   作者:恒生LIGHT云社區(qū)  
這篇文章主要介紹了Java使用Tessdata做OCR圖片文字識別的詳細思路,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

說到文字識別,目前除了用一些現(xiàn)成的api,大概就是 tessdatacanvas或者 ocrad等。

1、百度接口用過(可以自己去百度開發(fā)者申請,免費的),識別率吧,還可以,但也不是百分百的,但是次數(shù)使用有限制,雖然也是夠用,但是被限制總是害怕超過不讓用。
2、canvas的話是需要對圖片做具體的處理,涉及到圖片的翻轉(zhuǎn)、置灰、文字間隔的設(shè)定等等,成功率很高,但是公司產(chǎn)品驗證碼是各式各樣的,沒辦法用這種方法處理,所以暫時放棄了。
3、ocrad這個目前用過其.js版本,識別率還是比較低的,具體使用后面會再寫一篇文章介紹一下的。
雖然,網(wǎng)上對于 Tessdata的技術(shù)介紹文章一搜一大片,但是其實小仙真正用起來的時候,還是費了點周折的。:fendou:

思路:截全圖–截取元素圖片–處理–識別–輸出

注意:圖片截取格式統(tǒng)一為.jpg,用png會出問題。

1、添加項目依賴

在項目的pom.xml文件中,添加以下依賴

<!--<tess4j圖片識別>-->
<dependency>
	<groupId>net.java.dev.jna</groupId>
	<artifactId>jna</artifactId>
	<version>4.1.0</version>
</dependency>
<dependency>
	<groupId>net.sourceforge.tess4j</groupId>
	<artifactId>tess4j</artifactId>
	<version>2.0.1</version>
	<exclusions>
		<exclusion>
			<groupId>com.sun.jna</groupId>
			<artifactId>jna</artifactId>
		</exclusion>
	</exclusions>
</dependency>

2、從全圖中截取元素圖片

// 元素截圖

public static String[] elementscreenShot(WebElement element )
		throws Exception {
	WrapsDriver wrapsDriver = (WrapsDriver) element;
	long time = System.currentTimeMillis();

	// 截圖整個頁面
	File screen = ((TakesScreenshot) wrapsDriver.getWrappedDriver())
			.getScreenshotAs(OutputType.FILE);
	BufferedImage img = ImageIO.read(screen);
	// 獲得元素的高度和寬度
	int width = element.getSize().getWidth();
	int height = element.getSize().getHeight();
	// 創(chuàng)建一個矩形使用上面的高度,和寬度
	Rectangle rect = new Rectangle(width, height);
	// 得到元素的坐標
	Point p = element.getLocation();
	BufferedImage dest = img.getSubimage(p.getX(), p.getY(),
			(int) rect.getWidth(), (int) rect.getHeight());
	// 存為png格式
	ImageIO.write(dest, "png", screen);
	DateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
	FileSystemView fsv = FileSystemView.getFileSystemView();
	File com = fsv.getHomeDirectory(); // 這便是讀取桌面路徑的方法了
	String url = com.getPath() + "/test";
	File location = new File(url);
	if (!location.exists()) {
		location.mkdirs();
	}

	String imgPath = location.getAbsolutePath() + File.separator + "pic_"
			+ time + ".jpg";
	String cleanPath = location.getAbsolutePath();
	//存了原圖片和清楚后圖片的地址
	String[] imgpath = { imgPath, cleanPath };
	File targetFile = new File(imgPath);
	try {
		FileUtils.copyFile(screen, targetFile);
	} catch (IOException e1) {
		e1.printStackTrace();
	}
	//元素圖片路徑
	return imgpath;
}

3、對截取圖片進行處理:灰度化、二值化、去除干擾線等

以下是圖像處理的類,其中對于去除干擾線的操作還是慎用,可能會把文字也剔除掉。

public class CleanElementImage {
    /**
     *
     * @param sfile
     *            需要去噪的圖像
     * @param destDir
     *            去噪后的圖像保存地址
     * @throws IOException
     */
    public static void handlImage(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);
                // 圖像加亮(調(diào)整亮度識別率非常高)
                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);
//                    }
//                }
//            }
//        }
    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;
}
}

4、準備識別的語言包

默認是英文(識別字母和數(shù)字),如果要識別中文(數(shù)字 + 中文),需要制定語言包。
語言包可以指定一個路徑,有就可以了。
源碼下載地址
可以下載源碼,然后到下面這個路徑找到語言包,把語言包放到一個路徑:
例如:XXX/tessdata/下面。

tesseract.js-master.zip\tesseract.js-master\tests\assets\traineddata 

5、對圖片進行識別

/**
* 圖片識別
* @author wangy
* @date 2019-08-26
* @param parameter
*/
public static  String  ocrResult(WebElement element ) throws Exception {

	FileSystemView fsv = FileSystemView.getFileSystemView();
	File com=fsv.getHomeDirectory();    //這便是讀取桌面路徑的方法了
	String url = "";
	String os = System.getProperty("os.name");
	//識別系統(tǒng),找不同的語言包路徑
	if (os.indexOf("Windows") == -1) {
		url = "/opt/google/";
	} else {
		url = com.getPath();
	}
	//獲取元素截圖的路徑
        String path[]=Screenshot.elementscreenShot(element);
        //獲取未處理的截圖路徑
        String imgpath=path[0];
	String result = null;
	File imageFile = new File(imgpath);
	//要對圖片處理
        CleanElementImage.handlImage(imageFile,path[1]);
	ITesseract instance = new Tesseract();
	//讀取語言包的路徑地址
	instance.setDatapath(url + File.separator + "test" + File.separator
				+ "tessdata");
	// 默認是英文(識別字母和數(shù)字),如果要識別中文(數(shù)字 + 中文),需要制定語言包,這里是數(shù)字,所以沒用語言包
        // instance.setLanguage("chi_sim");
        //為了防止沒截完圖片就識別,做了一個簡單的循環(huán)
	try{
		String ocrResult=instance.doOCR(imageFile);
		if(imageFile.exists()&&ocrResult!=""){
			result=ocrResult;
		}else {
			while(true){
				Thread.sleep(1000);
				if(imageFile.exists()&&ocrResult!=""){
					result=ocrResult;
					break;
				}
			}
		}

	}catch(TesseractException e){
		System.out.println(e.getMessage());
	}
	return result;
}

這一部分由于項目問題,貼在這里做了特殊處理,原碼有一點點區(qū)別。大家使用,如果有什么問題,歡迎反饋!

6、成果

這里簡單放個對照,圖片將就看一下效果,識別結(jié)果大概90%以上吧:

到此這篇關(guān)于Java使用Tessdata做OCR圖片文字識別的詳細思路的文章就介紹到這了,更多相關(guān)java Tessdata圖片文字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中的private、protected、public和default的區(qū)別(詳解)

    Java中的private、protected、public和default的區(qū)別(詳解)

    下面小編就為大家?guī)硪黄狫ava中的private、protected、public和default的區(qū)別(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • Java后端限制頻繁請求和重復(fù)提交的實現(xiàn)

    Java后端限制頻繁請求和重復(fù)提交的實現(xiàn)

    很多用戶會請求過于頻繁或者是多次重復(fù)提交數(shù)據(jù),本文主要介紹了Java后端限制頻繁請求和重復(fù)提交的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • SpringBoot 集成MQTT實現(xiàn)消息訂閱的詳細代碼

    SpringBoot 集成MQTT實現(xiàn)消息訂閱的詳細代碼

    本文介紹了如何在SpringBoot中集成MQTT并實現(xiàn)消息訂閱,主要步驟包括添加依賴、配置文件設(shè)置、啟動類注解、MQTT配置類、消息處理器配置、主題緩存、動態(tài)數(shù)據(jù)庫主題配置以及消息處理服務(wù),感興趣的朋友跟隨小編一起看看吧
    2024-11-11
  • MyBatis-Plus聯(lián)表查詢及分頁代碼舉例

    MyBatis-Plus聯(lián)表查詢及分頁代碼舉例

    本文介紹了mybatis-plus-join工具的使用,該工具可以簡化mybatis-plus的聯(lián)表查詢,使得開發(fā)者可以以類似QueryWrapper的方式進行聯(lián)表查詢,無需手動編寫xml文件,感興趣的朋友跟隨小編一起看看吧
    2025-03-03
  • java的nio的使用示例分享

    java的nio的使用示例分享

    這篇教程展示了5個在Java編程的一些常見場景里使用NIO和NIO.2包的簡單示例,需要的朋友可以參考下
    2014-03-03
  • Spring中的@Scheduled源碼解析

    Spring中的@Scheduled源碼解析

    這篇文章主要介紹了Spring中的@Scheduled源碼解析,定時任務(wù)調(diào)度的基礎(chǔ)是ScheduledAnnotationBeanPostProcessor類,這是一個實現(xiàn)了BeanPostProcessor接口的后置處理器,需要的朋友可以參考下
    2023-09-09
  • java中文轉(zhuǎn)拼音工具類詳解

    java中文轉(zhuǎn)拼音工具類詳解

    這篇文章主要為大家詳細介紹了java中文轉(zhuǎn)拼音工具類的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • java @Data布爾值boolean的坑及解決

    java @Data布爾值boolean的坑及解決

    本文介紹了在使用Spring框架時,遇到的一個屬性命名規(guī)則問題,在Spring框架中,如果類的屬性名稱第一個字母小寫,第二個字母大寫,那么在調(diào)用set方法時,Spring會將屬性的后面的字母轉(zhuǎn)換為小寫,這種情況下,如果下游消費端調(diào)用得到的返回json串
    2024-10-10
  • 10個Elasticsearch查詢的實用技巧分享

    10個Elasticsearch查詢的實用技巧分享

    Elasticsearch是一個非常流行的搜索引擎,已經(jīng)成為了許多企業(yè)的首選解決方案。本文將向大家介紹10個實用的Elasticsearch查詢技巧,并配上對應(yīng)的代碼示例,希望對大家有所幫助
    2023-04-04
  • Java中wait與sleep的區(qū)別講解(wait有參及無參區(qū)別)

    Java中wait與sleep的區(qū)別講解(wait有參及無參區(qū)別)

    這篇文章主要介紹了Java中wait與sleep的講解(wait有參及無參區(qū)別),通過代碼介紹了wait()?與wait(?long?timeout?)?區(qū)別,wait(0)?與?sleep(0)區(qū)別,需要的朋友可以參考下
    2022-04-04

最新評論