读取tif格式插件_Jmeter识别图片验证码(二)制作Jmeter插件及验证识别成功率

接上篇,我们成功的安装了tesseract-OCR工具,这篇我们主要讲解制作jmeter插件VcodeExtractor的过程,并且如何利用这个插件来调用tesseract-OCR实现图片识别。


一、准备jar包

在开发之前我们要先做一下准备工作,需要jmeter/lib和jmeter/lib/ext下的jar包,ApacheJMeter_core.jar,slf4j-api-1.7.25.jar,logkit-2.0.jar(其中前两个在lib和ext目录下有现成的,而logkit-2.0.jar需要下载,可以到链接:https://pan.baidu.com/s/11i5tn0M2kTZMh65XaEVLAw 提取码:rgss 下载)。

另外还需要两个图形处理相关的jar包,在开发的过程中作为依赖库使用,

swingx-1.6.1.jar

下载链接:https://pan.baidu.com/s/1tOC2TgKhkp8_jhua6l5U_A提取码:djdy 。

jai_imageio-1.1.jar

下载链接:https://pan.baidu.com/s/1nMBJ4D4j5TDxPFLBTb2LLQ提取码:8fnx

二、将依赖的jar包添加到工程构建路径

在eclipse中创建VcodeExtractor工程,并创建lib路径。

将jar包拖拽到lib路径下(或直接复制,如果已经存在会提示是否overwrite覆盖掉),如图:

5a54b6600f1666e5e09d57bcb0757da1.png

e04fea792505c4515d745eb112b8cb68.png

然后右键点击lib文件,添加到构建路径

aa64ecfe74930ee8b7dbbf63cbfa2ecb.png

然后将所有需要的jar包添加即可。

3a8e7d1a0ae8311a53d1259ba2a7c2ba.png

添加完后点击应用并关闭,效果如图,

1544cc48dee43f45d117e6bb43afaacc.png

三、开发插件VcodeExtractor

这里要创建几个类,主要实现两部分功能,一个是调用三方工具tesseract-OCR进行图片识别,另一个是Jmeter插件UI部分。

在src目录下创建ImageIOhelper类,这个类主要包括两部分,前半部分将图片转化为tiff格式,后半部分通过降噪逻辑对图片进行处理,以便进行更好的识别。代码如下:

package com.test.laoli;import java.awt.Color;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import java.util.Iterator;import java.util.Locale; import javax.imageio.IIOImage;import javax.imageio.ImageIO;import javax.imageio.ImageReader;import javax.imageio.ImageWriteParam;import javax.imageio.ImageWriter;import javax.imageio.metadata.IIOMetadata;import javax.imageio.stream.ImageInputStream;import javax.imageio.stream.ImageOutputStream;import com.sun.media.imageio.plugins.tiff.TIFFImageWriteParam; public class ImageIOHelper{  //将图片格式转换为tif格式以更好地进行识别    public static File createImage(File imageFile, String imageFormat) {        File tempFile = null;        ImageInputStream iis = null;        ImageOutputStream ios = null;        ImageReader reader = null;        ImageWriter writer = null;        try {            Iterator readers = ImageIO.getImageReadersByFormatName(imageFormat);            reader = readers.next();            iis = ImageIO.createImageInputStream(imageFile);            reader.setInput(iis);             IIOMetadata streamMetadata = reader.getStreamMetadata();                        TIFFImageWriteParam tiffWriteParam = new TIFFImageWriteParam(Locale.CHINESE);            tiffWriteParam.setCompressionMode(ImageWriteParam.MODE_DISABLED);            Iterator writers = ImageIO.getImageWritersByFormatName("tiff");            writer = writers.next();             BufferedImage bi = removeBackgroud(reader.read(0));            IIOImage image = new IIOImage(bi,null,reader.getImageMetadata(0));            tempFile = tempImageFile(imageFile);             ios = ImageIO.createImageOutputStream(tempFile);            writer.setOutput(ios);            writer.write(streamMetadata, image, tiffWriteParam);         } catch (IOException e) {            e.printStackTrace();        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        } finally {            if(iis != null){                try {                    iis.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }            if(ios != null){                try {                    ios.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }            if(writer != null){                writer.dispose();            }            if(reader != null){                reader.dispose();            }         }        return tempFile;    }     private static File tempImageFile(File imageFile) {        String path = imageFile.getPath();        StringBuffer strB = new StringBuffer(path);        return new File(strB.toString().replaceFirst("jpg", "tif"));    }            //给图片降噪,建立如下降噪规则和方法,提高识别度    public static int isFilter(int colorInt) {          Color color = new Color(colorInt);        if ((color.getRed() > 85 && color.getRed() < 255)                 && (color.getGreen() > 85 && color.getGreen() < 255)                 && (color.getBlue() > 85 && color.getBlue() < 255)) {              return 1;          }          return 0;    }        public static BufferedImage removeBackgroud(BufferedImage img)              throws Exception {          int width = img.getWidth();          int height = img.getHeight();          for (int x = 0; x < width; ++x) {              for (int y = 0; y < height; ++y) {                  if (isFilter(img.getRGB(x, y)) == 1) {                     img.setRGB(x, y, Color.WHITE.getRGB());                  }            }          }          return img;    }     }

然后创建OCR类,通过Process调用安装好的三方工具tesseract-OCR进行图片识别,调用命令的基本形式如下tesseract xxx.tif 1 -l eng,代码如下:

package com.test.laoli;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List; public class OCR {    private final String LANG_OPTION = "-l";    private final String EOL = System.getProperty("line.separator");    //第三方图形图像识别工具tesseract-OCR的安装目录    private String tessPath = "D://Tesseract-OCR";     public String recognizeText(File imageFile,String imageFormat) {        File tempImage = ImageIOHelper.createImage(imageFile,imageFormat);        File outputFile = new File(imageFile.getParentFile(),"output" + imageFile.getName());        StringBuffer sb = new StringBuffer();        List<String> cmd = new ArrayList<String>();         cmd.add(tessPath+"//tesseract");        cmd.add("");        cmd.add(outputFile.getName());        cmd.add(LANG_OPTION);        cmd.add("eng");             ProcessBuilder pb = new ProcessBuilder();        pb.directory(imageFile.getParentFile());         cmd.set(1, tempImage.getName());        pb.command(cmd);        pb.redirectErrorStream(true);         Process process = null;        BufferedReader in = null;        int wait;        try {            process = pb.start();            //通过Process调用已经安装的Tesseract程序,调用命令基本形式为:tesseract xxx.tif 1 -l eng            wait = process.waitFor();            if(wait == 0){                in = new BufferedReader(new InputStreamReader(new FileInputStream(outputFile.getAbsolutePath()+".txt"),"UTF-8"));                String str;                while((str = in.readLine())!=null){                    sb.append(str).append(EOL);                }                in.close();             }else{                 tempImage.delete();            }            new File(outputFile.getAbsolutePath()+".txt").delete();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (InterruptedException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } finally {            if(in != null){                try {                    in.close();                } catch (IOException e) {                    // TODO Auto-generated catch block                    e.printStackTrace();                }            }        }         tempImage.delete();        return sb.toString();    }}

然后创建VcodeExtractor类,他主要继承AbstractScopedTestElement类,实现PostProcessor接口的process方法,处理利用tesseract-OCR读取验证码信息的逻辑控制,代码如下:

package com.test.laoli;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.Serializable; import org.apache.jmeter.processor.PostProcessor;import org.apache.jmeter.samplers.SampleResult;import org.apache.jmeter.testelement.AbstractScopedTestElement;import org.apache.jmeter.threads.JMeterContext;import org.apache.jmeter.threads.JMeterVariables;import org.slf4j.Logger;import org.slf4j.LoggerFactory; public class VcodeExtractor extends AbstractScopedTestElement implements PostProcessor, Serializable{    private static final long serialVersionUID = 1L;       private static final Logger log = LoggerFactory.getLogger(VcodeExtractor.class);        @Override    public void process() {         // TODO Auto-generated method stub        JMeterContext context = getThreadContext();        SampleResult previousResult = context.getPreviousResult();        if (previousResult == null) {            return;        }        log.debug("VcodeExtractor processing result");         String status = previousResult.getResponseCode();        int id = context.getThreadNum();        //String imageName = id + ".jpg";        String path = "D:\\1\\1.png";         if(status.equals("200")){            byte[] buffer = previousResult.getResponseData();            FileOutputStream out = null;            File file = null;            try {                file = new File(path);                out = new FileOutputStream(file);                out.write(buffer);                out.flush();             } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            } finally {                if(out != null){                    try {                        out.close();                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }            }               try {                   String vcode = new OCR().recognizeText(file, "png");                 vcode = vcode.replace(" ", "").trim();                                JMeterVariables var = context.getVariables();                var.put("vcode", vcode);                var.put("vuser", String.valueOf(id));                } catch (Exception e) {                    e.printStackTrace();                }            }     } }

然后就是VcodeExtractorGUI类,主要实现一个可视化界面,可以在Jmeter中直接添加。代码如下:

package com.test.laoli;import org.apache.jmeter.processor.gui.AbstractPostProcessorGui;import org.apache.jmeter.testelement.TestElement; public class VcodeExtractorGUI extends AbstractPostProcessorGui{    private static final long serialVersionUID = 1L;        @Override    public TestElement createTestElement() {        // TODO Auto-generated method stub        VcodeExtractor extractor = new VcodeExtractor();        modifyTestElement(extractor);        return extractor;    }     @Override    public String getLabelResource() {        // TODO Auto-generated method stub        return this.getClass().getName();    }     @Override    public String getStaticLabel() {      //设置显示名称        // TODO Auto-generated method stub        return "VcodeExtractor";    }     @Override    public void modifyTestElement(TestElement extractor) {        // TODO Auto-generated method stub        super.configureTestElement(extractor);     }}

最后是主函数,程序启动入口。代码如下:

package com.test.laoli; import java.io.File;  public class TestOCR {     public static void main(String[] args) {            String path = "D:\\1\\1.png";                  try {                     String valCode = new OCR().recognizeText(new File(path), "png");                     System.out.println(valCode);                 } catch (Exception e) {                  e.printStackTrace();              }                 }          }  

  这样我们就可以执行程序进行测试,首先我们下载一张图片验证码到代码中设置的路径下,然后执行程序,如图:

b8f16e8444f0d56de30a7939f534b0a2.png

44749e1d8d78656b2ee19284a30955d8.png

可以看到,程序可以执行成功,但是验证码(71422)中的最后一位“2”并未识别出来。这个我们先不管,最后再验证成功率是多少。

四、将开发的组件导出jar包

首先,我们右键点击工程,弹出如下提示对话框,

a8df7f555c097f001ad925ea74680be9.png

我们点击导出,并选择导出路径和方式,就可以成功将工程导出为jar包。

9759636d8f1896d7f7a864314dac4738.png

19ee59e0d00cb9522787c1b94340ecde.png

f8e5671692aa60f47e10341bb07c051e.png

然后我们在保存jar包的路径下先下载一张图片验证码,使用win+R输入cmd打开命令行,切换到保存jar包的路径下,执行shell命令,java-jar VcodeExtractor.Jar命令,如图:

adec5ca501d9521215d311337055363e.png

fd6d0ec2fae784a85747ffa3f0c3fe6d.png

这就证明我们生成的jar包可以使用。但是精度还是有问题·····

五、利用Jmeter完成自动化接口测试

首先我们,将生成的jar包和相应的文件夹复制到jmeter程序中的lib/ext路径下,然后启动jmeter程序。

978d7a617ba0f31c38c0729ee2747016.png

f8fa1bf9fe08df067ee20d934c96f839.png

如图,我先是调用了获取图片验证码的接口,然后在他的取样器下添加了我们自己制作的插件VcodeExtractor,这个插件默认将识别的验证码定义为变量${vcode},所以我们添加第二个接口将验证法通过接口发送给后端验证正确性。

1bf6b23f57ece7ab2422ac38124441ed.png

2b05e383619da9b66552f1fab51ec6d1.png

fd289c105624026f4c1843910e27df74.png

0c8ed2182d15b46ac26273fcff975b9e.png

这就说明我们制作的VcodeExtractor插件是可以用的,接下来重点来了,老李非常想知道这个OCR工具识别图片验证码的成功率是多少,于是就将线程调到了30,并添加了聚合报告来进行查看。如图:

e16eaa902c390aacd8b96473bd340185.png

看到聚合报告的的一刹那,瞬间好失望呀,这,这····还有得救吗?

话说,经过图片训练可以提高识别率,但是关于这方面的知识还需要继续学习啊,继续加油吧。

82a58e2d255ac0221b098068d3dcb160.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值