需要源码和图片集请点赞关注收藏后评论区留下QQ或者私信~~~

一、自动识别验证码

验证码图片中最简单的是数字验证码,一张再普通不过的验证码拿到之后要进行以下步骤的处理

1:首先对图片适当裁剪,先去掉外部的空白区域,再把每个数字所处的区域单独抠出来

2:对每个数字方块做切割 一般按照九宫格切为九块

一般情况下 图片中的数字颜色较深,其他区域颜色较浅,通过判断每个方格上的像素点颜色深浅就能得知该方格是否有线条经过,获取像素点的颜色深浅主要有以下几个步骤

1:调用bitmap对象的getPixel 获得指定x y坐标像素点的颜色对象

2:调用Integet类的toHexString方法 把颜色对象转换为字符串对象

3:第二步得到一个长度为8的字符串,其中前两位表示透明度,第三四位表示红色浓度,第五六位表示绿色浓度,第七八位表示蓝色浓度,另外,需要把十六进制的颜色浓度值转换位十进制的浓度值

接下来从外部掉用getNumber方法,即可从验证码位图识别出验证码数字,这个验证码图片识别出验证码数字,这个验证码图片可能来自本地也可能来自网络,

运行App后结果如下 什么都不加时识别正确率较高,当加了干扰线和字母时识别率将会大大降低,因为算法目前不支持字母的识别

加了干扰之后准确率直线下滑

通过上述图例也可以发现防止验证码被破解至少包含两个手段 一是扩大干扰力度,二是增加字符种类

代码如下

Java类

package com.example.face;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;import com.example.face.util.CodeAnalyzer;import java.io.IOException;
import java.io.InputStream;
import java.util.List;import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;@SuppressLint({"DefaultLocale", "SetTextI18n"})
public class VerifyCodeActivity extends AppCompatActivity {private final static String TAG = "VerifyCodeActivity";private final static String mCodeUrl = "http://192.168.1.5:8080/HttpServer/generateCode?char_type=%d&disturber_type=%d";private CheckBox ck_source; // 声明一个复选框对象private LinearLayout ll_local; // 声明一个线性视图对象private LinearLayout ll_network; // 声明一个线性视图对象private ImageView iv_code; // 声明一个图像视图对象private TextView tv_code; // 声明一个文本视图对象private boolean isGetting = false; // 是否正在获取验证码@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_verify_code);ck_source = findViewById(R.id.ck_source);ll_local = findViewById(R.id.ll_local);ll_network = findViewById(R.id.ll_network);iv_code = findViewById(R.id.iv_code);iv_code.setOnClickListener(v -> getImageCode(mCharType, mDisturberType));tv_code = findViewById(R.id.tv_code);ck_source.setOnCheckedChangeListener((buttonView, isChecked) -> {ll_local.setVisibility(isChecked ? View.GONE : View.VISIBLE);ll_network.setVisibility(isChecked ? View.VISIBLE : View.GONE);});initCodeSpinner(); // 初始化验证码图片下拉框initCharSpinner(); // 初始化字符类型下拉框initDisturbSpinner(); // 初始化干扰类型下拉框}// 初始化验证码图片下拉框private void initCodeSpinner() {ArrayAdapter<String> codeAdapter = new ArrayAdapter<>(this,R.layout.item_select, codeDescArray);Spinner sp_code = findViewById(R.id.sp_code);sp_code.setPrompt("请选择验证码图片");sp_code.setAdapter(codeAdapter);sp_code.setOnItemSelectedListener(new CodeSelectedListener());sp_code.setSelection(0);}private String[] codeDescArray={"第一张验证码", "第二张验证码", "第三张验证码", "第四张验证码", "第五张验证码"};private int[] codeResArray={R.drawable.code1, R.drawable.code2, R.drawable.code3, R.drawable.code4, R.drawable.code5 };class CodeSelectedListener implements AdapterView.OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {Bitmap bitmap = BitmapFactory.decodeResource(getResources(), codeResArray[arg2]);showVerifyCode(bitmap); // 识别并显示验证码数字}public void onNothingSelected(AdapterView<?> arg0) {}}// 初始化字符类型下拉框private void initCharSpinner() {ArrayAdapter<String> charAdapter = new ArrayAdapter<>(this,R.layout.item_select, charDescArray);Spinner sp_char = findViewById(R.id.sp_char);sp_char.setPrompt("请选择字符类型");sp_char.setAdapter(charAdapter);sp_char.setOnItemSelectedListener(new CharSelectedListener());sp_char.setSelection(0);}private int mCharType = 0; // 字符类型private String[] charDescArray={"纯数字", "字母加数字"};class CharSelectedListener implements AdapterView.OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {mCharType = arg2;getImageCode(mCharType, mDisturberType); // 从服务器获取验证码图片}public void onNothingSelected(AdapterView<?> arg0) {}}// 初始化干扰类型下拉框private void initDisturbSpinner() {ArrayAdapter<String> disturbAdapter = new ArrayAdapter<>(this,R.layout.item_select, disturbDescArray);Spinner sp_disturb = findViewById(R.id.sp_disturb);sp_disturb.setPrompt("请选择干扰类型");sp_disturb.setAdapter(disturbAdapter);sp_disturb.setOnItemSelectedListener(new DisturbSelectedListener());sp_disturb.setSelection(0);}private int mDisturberType = 0; // 干扰类型private String[] disturbDescArray={"干扰点", "干扰线"};class DisturbSelectedListener implements AdapterView.OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {mDisturberType = arg2;getImageCode(mCharType, mDisturberType); // 从服务器获取验证码图片}public void onNothingSelected(AdapterView<?> arg0) {}}// 从服务器获取验证码图片private void getImageCode(int char_type, int disturber_type) {if (!ck_source.isChecked() || isGetting) {return;}isGetting = true;String imageUrl = String.format(mCodeUrl, char_type, disturber_type);OkHttpClient client = new OkHttpClient(); // 创建一个okhttp客户端对象// 创建一个GET方式的请求结构Request request = new Request.Builder().url(imageUrl).build();Call call = client.newCall(request); // 根据请求结构创建调用对象// 加入HTTP请求队列。异步调用,并设置接口应答的回调方法call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) { // 请求失败isGetting = false;// 回到主线程操纵界面runOnUiThread(() -> tv_code.setText("下载网络图片报错:"+e.getMessage()));}@Overridepublic void onResponse(Call call, final Response response) { // 请求成功InputStream is = response.body().byteStream();// 从返回的输入流中解码获得位图数据Bitmap bitmap = BitmapFactory.decodeStream(is);isGetting = false;// 回到主线程操纵界面runOnUiThread(() -> showVerifyCode(bitmap));}});}// 识别并显示验证码数字private void showVerifyCode(Bitmap bitmap) {String number = CodeAnalyzer.getNumber(bitmap); // 从验证码位图获取验证码数字iv_code.setImageBitmap(bitmap);tv_code.setText("自动识别得到的验证码是:"+number);
//        List<Bitmap> bitmapList = CodeAnalyzer.splitImage(bitmap);
//        ImageView iv1 = findViewById(R.id.iv1);
//        ImageView iv2 = findViewById(R.id.iv2);
//        ImageView iv3 = findViewById(R.id.iv3);
//        ImageView iv4 = findViewById(R.id.iv4);
//        iv1.setImageBitmap(bitmapList.get(0));
//        iv2.setImageBitmap(bitmapList.get(1));
//        iv3.setImageBitmap(bitmapList.get(2));
//        iv4.setImageBitmap(bitmapList.get(3));}}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><CheckBoxandroid:id="@+id/ck_source"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="验证码是否来自服务器"android:textColor="#000000"android:textSize="17sp" /><LinearLayoutandroid:id="@+id/ll_local"android:layout_width="match_parent"android:layout_height="40dp"android:paddingLeft="5dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"android:text="请选择验证码图片 "android:textColor="#000000"android:textSize="17sp" /><Spinnerandroid:id="@+id/sp_code"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center_vertical"android:spinnerMode="dialog" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_network"android:layout_width="match_parent"android:layout_height="40dp"android:visibility="gone"><Spinnerandroid:id="@+id/sp_char"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center_vertical"android:spinnerMode="dialog" /><Spinnerandroid:id="@+id/sp_disturb"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center_vertical"android:spinnerMode="dialog" /></LinearLayout><ImageViewandroid:id="@+id/iv_code"android:layout_width="match_parent"android:layout_height="100dp" /><TextViewandroid:id="@+id/tv_code"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="5dp"android:textColor="#000000"android:textSize="17sp" /><LinearLayoutandroid:layout_width="match_parent"android:layout_height="100dp"android:layout_marginTop="20dp"><ImageViewandroid:id="@+id/iv1"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /><ImageViewandroid:id="@+id/iv2"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /><ImageViewandroid:id="@+id/iv3"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /><ImageViewandroid:id="@+id/iv4"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /></LinearLayout></LinearLayout>

创作不易 觉得有帮助请点赞关注收藏~~~

Android 开发人脸识别之自动识别验证码功能讲解及实现(超详细 附源码)相关推荐

  1. 【Android App】在线语音识别功能实现(使用云知声平台与WebSocket 超详细 附源码)

    需要源码和相关资源请点赞关注收藏后评论区留下QQ~~~ 一.在线语音识别 云知声的语音识别同样采用WebSocket接口,待识别的音频流支持MP3和PCM两种格式,对于在线语音识别来说,云知声使用JS ...

  2. Android App开发语音处理之系统自带的语音引擎、文字转语音、语音识别的讲解及实战(超详细 附源码)

    需要源码请点赞关注收藏后评论区留下QQ~~~ 一.系统自带的语音引擎 语音播报的本质是将书面文字转换成自然语言的音频流,这个转换操作被称作语音合成,又称TTS(从文本到语音)在转换过程中,为了避免机械 ...

  3. 【Android App】实现在线语音合成功能(使用云知声平台和WebSocket 超详细 附源码)

    需要源码和Jar包请点赞关注收藏后评论区留下QQ~~~ 一.在线语音合成 虽然国产智能机大多集成了中文语音引擎,但是系统自带的语音工具无法满足商用要求,功能单一,所以势必引入第三方的语音引擎,依靠第三 ...

  4. Android 开发中原始音频的录播和和自定义音频控制条的讲解及实战(超详细 附源码)

    需要源码请点赞关注收藏后评论区留下QQ~~~ 一.原始音频的录播 语音通话功能要求实时传输,如果使用MediaRecorder与MediaPlayer组合,那么只能整句话都录完并编码好了才能传给对方去 ...

  5. 【Android +Tensroflow Lite】实现从基于机器学习语音中识别指令讲解及实战(超详细 附源码和演示视频)

    需要源码和配置文件请点赞关注收藏后评论区留言~~~ 一.基于机器学习的语音推断 Tensorflow基于分层和模块化的设计思想,整个框架以C语言的编程接口为界,分为前端和后端两大部分 Tensorfl ...

  6. Android开发音效中录制WAV音频和录制MP3音频的讲解及实战(超详细 附源码)

    需要源码请点赞关注收藏后评论区留下QQ~~~ 一.录制WAV音频 无论是MediaRecoredr录制的AMR和AAC音频,还是AudioRecord录制的PCM音频,都不能在计算机上直接播放,因为它 ...

  7. 【Python+百度API】实现人脸识别和颜值检测系统(包括人脸数量、年龄、颜值评分、性别、种族、表情检测)(超详细 附源码)

    需要源码请点赞关注收藏后评论区留下QQ~~~ 本系统根据已有的模型上改写,添加了在给照片打分的同时可以显示照片,这样显得更加直观和真实 一.百度API文档 如需要请自行前往官网查询文档相关内容 百度A ...

  8. Android开发音效增强中铃声播放Ringtone及声音池调度SoundPool的讲解及实战(超详细 附源码)

    需要源码请点赞关注收藏后评论区留下QQ~~~ 一.铃声播放 虽然媒体播放器MediaPlayer既可用来播放视频,也可以用来播放音频,但是在具体的使用场合,MediaPlayer存在某些播音方面的不足 ...

  9. Android App开发实战项目之仿喜马拉雅的听说书App实现(超详细 附源码和演示视频)

    需要全部源码请点赞关注收藏后评论区留下QQ~~~ 一.需求分析 用户不仅能在平台上收听音频,还能成为内容创作者,总之长音频分享平台需要满足两种角色的使用:一种是作为内容创作者发布自己的音频,另一种是作 ...

最新文章

  1. 干货!这里有一份神经网络入门指导,请收下!
  2. pb mdi窗口多sheet_Filecoin奖励测试网8月3日开启,主网启动窗口:8月31日至9月21日...
  3. go语言条件语句 if else
  4. 前端必看 | 2D游戏化互动入门基础知识
  5. javascript四个方向无间隙滚动合集(多浏览器IE,firefox兼容)
  6. java junit4_JUnit4使用Java5中的单元测试
  7. 完整解决方案:让你的IIS 支持PHP方法
  8. Null对象模式的用法
  9. tomcat相关配置技巧梳理 (修改站点目录、多项目部署、限制ip访问、大文件上传超时等)...
  10. python的numpy是什么_python中numpy是什么
  11. SPSS下载安装教程
  12. Verilog实现的格雷码与二进制码的互相转换
  13. 05 js面向对象(属性操作符,创建对象)
  14. 105套抖音快闪模板
  15. win7 变wifi热点
  16. WPS 操作之在指定页插入页码
  17. CSS设置背景图宽度100%,高度自适应
  18. 电脑端破解之破解注册码
  19. 遇见2016年最值得期待的新产品
  20. 修改命令提示符和PS1变量

热门文章

  1. ESXI挂载移动(机械)硬盘详细教程
  2. 【C语言课程设计】【C语言】学生成绩管理系统
  3. 基于ASP.NET开发的企信通源码 短信管理平台源码
  4. 游戏SKU采集出入库-Xposed Hook
  5. 《函数调用时参数、返回值所做的优化处理+编译器NRV优化》
  6. 公安三维电子沙盘 数字沙盘方案书
  7. 李峋同款爱心代码【有声版】
  8. VC++使用zlib压缩及解压数据,使用base64编码及解码数据(附源码)
  9. FOREX嘉盛外汇 forex-jsfx.com外汇入门新手必看:外汇交易系统中还存在着这些陷阱!
  10. (4.7-4.13)【大数据新闻速递】上海、广州、青海、贵阳大力发展大数据产业;2026年中国大数据市场规模预计达365亿美元