我们在使用WebView这个控件的时候,经常需要去写一些方法供H5页面调用,我在开发的过程中遇到这样一个需求,通过点击H5页面上的按钮调用Android手机的图库,并且进行上传图片。
通过网上查找资料,找到了WebChromeClient的一个隐藏方法openFileChooser();
- Android3.0以下的SDK,openFileChooser仅有一个参数:openFileChooser(ValueCallback< Uri > uploadFile)。
- Android3.0以上的SDK,openFileChooser有两个参数:openFileChooser(ValueCallback< Uri > uploadFile, String acceptType)。
- Android4.1以上的SDK,openFileChooser增加到三个参数:openFileChooser(ValueCallback< Uri > uploadFile, String acceptType, String capture)。
- Android5.0以上的SDK,openFileChooser被onShowFileChooser给替代了,onShowFileChooser(WebView webview,ValueCallback< Uri > filePathCallback,FileChooserParams fileChooserParams)。
Android6.0的SDK,WebChromeClient.class里的openFileChooser和onShowFileChooser的源码:
方法openFileChooser:
/** * Tell the client to open a file chooser. * @param uploadFile A ValueCallback to set the URI of the file to upload. * onReceiveValue must be called to wake up the thread.a * @param acceptType The value of the 'accept' attribute of the input tag * associated with this file picker. * @param capture The value of the 'capture' attribute of the input tag * associated with this file picker. * * @deprecated Use {@link #showFileChooser} instead. * @hide This method was not published in any SDK version. */ @SystemApi @Deprecated public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture) { uploadFile.onReceiveValue(null); }
方法onShowFileChooser:
/** * Tell the client to show a file chooser. * * This is called to handle HTML forms with 'file' input type, in response to the * user pressing the "Select File" button. * To cancel the request, call <code>filePathCallback.onReceiveValue(null)</code> and * return true. * * @param webView The WebView instance that is initiating the request. * @param filePathCallback Invoke this callback to supply the list of paths to files to upload, * or NULL to cancel. Must only be called if the * <code>showFileChooser</code> implementations returns true. * @param fileChooserParams Describes the mode of file chooser to be opened, and options to be * used with it. * @return true if filePathCallback will be invoked, false to use default handling. * * @see FileChooserParams */ public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { return false; }
来看下代码:
这是一个内部类,重写WebChromeClient的openFileChooser和onShowFileChooser。
/** * 内部类 */ class MyWebChromeClient extends WebChromeClient { // For Android 3.0+ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { if (mUploadMessage != null) return; mUploadMessage = uploadMsg; selectImage(RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP); } // For Android < 3.0 public void openFileChooser(ValueCallback<Uri> uploadMsg) { openFileChooser(uploadMsg, ""); } // For Android > 4.1.1 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { openFileChooser(uploadMsg, acceptType); } // For Android 5.0+ public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { mUploadCallbackAboveL = filePathCallback; selectImage(RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP); return true; } @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); } }
openFileChooser和onShowFileChooser方法,当Web页面上点击了<input type="file"/>
的标签时,不同版本的SDK调用openFileChooser或者onShowFileChooser。
选择完图片后,进入onActivityResult,根据不同的requestCode值区分开AndroidSDK 5.0以上和5.0以下,5.0以下传回Uri对象,5.0以上传回Uri数组。其中处理下onActivityResult传回来的Intent data,将Intent data转换成Uri。
/**选择后,回传值*/ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (mUploadMessage == null && mUploadCallbackAboveL == null) { return; } Uri uri = null; switch (requestCode) { case RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP: uri = afterChosePic(data); if (mUploadMessage != null) { mUploadMessage.onReceiveValue(uri); mUploadMessage = null; } break; case RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP: try { uri = afterChosePic(data); if (uri == null) { mUploadCallbackAboveL.onReceiveValue(new Uri[] { }); mUploadCallbackAboveL = null; break; } if (mUploadCallbackAboveL != null && uri != null) { mUploadCallbackAboveL.onReceiveValue(new Uri[] { uri }); mUploadCallbackAboveL = null; } } catch (Exception e) { mUploadCallbackAboveL = null; e.printStackTrace(); } break; } }
下面把完整的代码贴上来:
WebViewActivity.java
package com.lwd.webviewupimg; import java.io.File; import android.annotation.SuppressLint; import android.app.Activity; import android.content.ContentResolver; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore.Images.ImageColumns; import android.view.KeyEvent; import android.view.View; import android.webkit.ValueCallback; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebSettings.LayoutAlgorithm; import android.webkit.WebView; import android.webkit.WebViewClient; /** * @author lwd * @create 2016年8月17日 */ @SuppressLint("SetJavaScriptEnabled") public class WebViewActivity extends Activity{ private WebView webview; private ValueCallback<Uri> mUploadMessage; private ValueCallback<Uri[]> mUploadCallbackAboveL; private final int RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP = 1; private final int RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP = 2; private String url = "";//这里添加含有图片上传功能的H5页面访问地址即可。 String compressPath = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_welcome); initData(); } public void initData() { webview = (WebView) findViewById(R.id.webview); initWebView(); webview.loadUrl(url); } @SuppressWarnings("deprecation") private void initWebView(){ webview.setScrollBarStyle(View.GONE); webview.getSettings().setJavaScriptEnabled(true); webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); webview.getSettings().setDomStorageEnabled(false); webview.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT); webview.getSettings().setPluginState(WebSettings.PluginState.ON); webview.getSettings().setAllowFileAccess(true); webview.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); webview.getSettings().setLayoutAlgorithm(LayoutAlgorithm.NORMAL); webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null); webview.getSettings().setUseWideViewPort(true); webview.getSettings().setLoadWithOverviewMode(true); webview.getSettings().setAllowContentAccess(true); webview.requestFocus(); webview.setWebViewClient(new WebClient()); webview.setWebChromeClient(new MyWebChromeClient()); } /**选择后,回传值*/ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (mUploadMessage == null && mUploadCallbackAboveL == null) { return; } Uri uri = null; switch (requestCode) { case RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP: uri = afterChosePic(data); if (mUploadMessage != null) { mUploadMessage.onReceiveValue(uri); mUploadMessage = null; } break; case RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP: try { uri = afterChosePic(data); if (uri == null) { mUploadCallbackAboveL.onReceiveValue(new Uri[] { }); mUploadCallbackAboveL = null; break; } if (mUploadCallbackAboveL != null && uri != null) { mUploadCallbackAboveL.onReceiveValue(new Uri[] { uri }); mUploadCallbackAboveL = null; } } catch (Exception e) { mUploadCallbackAboveL = null; e.printStackTrace(); } break; } } /** * 选择照片后结束 * @param data */ private Uri afterChosePic(Intent data) { if (data == null) { return null; } String path = getRealFilePath(data.getData()); String[] names = path.split("\\."); String endName = null; if (names != null) { endName = names[names.length - 1]; } if (endName != null) { compressPath = compressPath.split("\\.")[0] + "." + endName; } File newFile; try { newFile = FileUtils.compressFile(path, compressPath); } catch (Exception e) { newFile = null; } return Uri.fromFile(newFile); } /** * 根据Uri获取图片文件的绝对路径 */ public String getRealFilePath(final Uri uri) { if (null == uri) { return null; } final String scheme = uri.getScheme(); String data = null; if (scheme == null) { data = uri.getPath(); } else if (ContentResolver.SCHEME_FILE.equals(scheme)) { data = uri.getPath(); } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) { Cursor cursor = getContentResolver().query(uri, new String[] { ImageColumns.DATA }, null, null, null); if (null != cursor) { if (cursor.moveToFirst()) { int index = cursor.getColumnIndexOrThrow(ImageColumns.DATA); if (index > -1) { data = cursor.getString(index); } } cursor.close(); } } return data; } @Override public void onBackPressed() { super.onBackPressed(); if(webview.canGoBack()){ webview.goBack(); }else{ finish(); } } private class WebClient extends WebViewClient { @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); } @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { view.loadUrl(url); return true; } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); } } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) { webview.goBack(); return true; } return super.onKeyDown(keyCode, event); } /**打开图库,同时处理图片(项目业务需要统一命名)*/ private void selectImage(int resultCode) { compressPath = Environment.getExternalStorageDirectory().getPath() + "/QWB/temp"; File file = new File(compressPath); if (!file.exists()) { file.mkdirs(); } compressPath = compressPath + File.separator + "compress.png"; File image = new File(compressPath); if (image.exists()) { image.delete(); } Intent intent = new Intent( Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, resultCode); } /** * 内部类 */ class MyWebChromeClient extends WebChromeClient { //openFileChooser(隐藏方法)仅适用android5.0以下的环境,android5.0及以上使用onShowFileChooser // For Android 3.0+ public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { if (mUploadMessage != null) return; mUploadMessage = uploadMsg; selectImage(RESULT_CODE_PICK_FROM_ALBUM_BELLOW_LOLLILOP); } // For Android < 3.0 public void openFileChooser(ValueCallback<Uri> uploadMsg) { openFileChooser(uploadMsg, ""); } // For Android > 4.1.1 public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture) { openFileChooser(uploadMsg, acceptType); } // For Android 5.0+ public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) { mUploadCallbackAboveL = filePathCallback; selectImage(RESULT_CODE_PICK_FROM_ALBUM_ABOVE_LOLLILOP); return true; } @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); } } }
FileUtils.java
package com.lwd.webviewupimg; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Matrix; import android.media.ExifInterface; import android.text.TextUtils; import android.util.Log; public class FileUtils { /** * 把图片压缩到200K * * @param oldpath * 压缩前的图片路径 * @param newPath * 压缩后的图片路径 * @return */ public static File compressFile(String oldpath, String newPath) { Bitmap compressBitmap = FileUtils.decodeFile(oldpath); Bitmap newBitmap = ratingImage(oldpath, compressBitmap); ByteArrayOutputStream os = new ByteArrayOutputStream(); newBitmap.compress(CompressFormat.PNG, 100, os); byte[] bytes = os.toByteArray(); File file = null ; try { file = FileUtils.getFileFromBytes(bytes, newPath); } catch (Exception e) { e.printStackTrace(); }finally{ if(newBitmap != null ){ if(!newBitmap.isRecycled()){ newBitmap.recycle(); } newBitmap = null; } if(compressBitmap != null ){ if(!compressBitmap.isRecycled()){ compressBitmap.recycle(); } compressBitmap = null; } } return file; } private static Bitmap ratingImage(String filePath,Bitmap bitmap){ int degree = readPictureDegree(filePath); return rotaingImageView(degree, bitmap); } /** * 旋转图片 * @param angle * @param bitmap * @return Bitmap */ public static Bitmap rotaingImageView(int angle , Bitmap bitmap) { //旋转图片 动作 Matrix matrix = new Matrix();; matrix.postRotate(angle); System.out.println("angle2=" + angle); // 创建新的图片 Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); return resizedBitmap; } /** * 读取图片属性:旋转的角度 * @param path 图片绝对路径 * @return degree旋转的角度 */ public static int readPictureDegree(String path) { int degree = 0; try { ExifInterface exifInterface = new ExifInterface(path); int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } } catch (IOException e) { e.printStackTrace(); } return degree; } /** * 把字节数组保存为一个文件 * * @param b * @param outputFile * @return */ public static File getFileFromBytes(byte[] b, String outputFile) { File ret = null; BufferedOutputStream stream = null; try { ret = new File(outputFile); FileOutputStream fstream = new FileOutputStream(ret); stream = new BufferedOutputStream(fstream); stream.write(b); } catch (Exception e) { // log.error("helper:get file from byte process error!"); e.printStackTrace(); } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { // log.error("helper:get file from byte process error!"); e.printStackTrace(); } } } return ret; } /** * 图片压缩 * * @param fPath * @return */ public static Bitmap decodeFile(String fPath) { BitmapFactory.Options opts = new BitmapFactory.Options(); opts.inJustDecodeBounds = true; opts.inDither = false; // Disable Dithering mode opts.inPurgeable = true; // Tell to gc that whether it needs free opts.inInputShareable = true; // Which kind of reference will be used to BitmapFactory.decodeFile(fPath, opts); final int REQUIRED_SIZE = 200; int scale = 1; if (opts.outHeight > REQUIRED_SIZE || opts.outWidth > REQUIRED_SIZE) { final int heightRatio = Math.round((float) opts.outHeight / (float) REQUIRED_SIZE); final int widthRatio = Math.round((float) opts.outWidth / (float) REQUIRED_SIZE); scale = heightRatio < widthRatio ? heightRatio : widthRatio;// } Log.i("scale", "scal ="+ scale); opts.inJustDecodeBounds = false; opts.inSampleSize = scale; Bitmap bm = BitmapFactory.decodeFile(fPath, opts).copy(Config.ARGB_8888, false); return bm; } /** * 创建目录 * @param path */ public static void setMkdir(String path) { File file = new File(path); if(!file.exists()) { file.mkdirs(); Log.e("file", "目录不存在 创建目录 "); }else{ Log.e("file", "目录存在"); } } /** * 获取目录名称 * @param url * @return FileName */ public static String getFileName(String url) { int lastIndexStart = url.lastIndexOf("/"); if(lastIndexStart!=-1) { return url.substring(lastIndexStart+1, url.length()); }else{ return null; } } /** * 删除该目录下的文件 * * @param path */ public static void delFile(String path) { if (!TextUtils.isEmpty(path)) { File file = new File(path); if (file.exists()) { file.delete(); } } } }
相关推荐
本文将深入探讨如何完美解决WebView上传图库图片的兼容性问题。 首先,我们来理解WebView的基本用法。WebView是Android SDK中的一个类,它通过加载HTML、CSS和JavaScript代码,可以在应用程序内部显示网页。为了...
基于风光负荷不确定性的微电网两阶段鲁棒优化模型:投资与运行成本的综合考虑及CCG算法的Matlab+Yamilp+CPLEX求解方法,考虑风光负荷的不确定性,构建了微电网两阶段鲁棒优化容量配置模型,第一阶段目标函数为微电网投资成本,第二阶段目标函数为微电网的运行成本。 采用CCG算法求解。 包含非线性项的线性化处理。 程序代码matlab+yamilp+CPLEX ,核心关键词: 微电网; 两阶段鲁棒优化; 容量配置模型; CCG算法; 线性化处理; MATLAB; YAMILP; CPLEX 用分号分隔每个关键词的结果为: 微电网; 两阶段鲁棒优化; 容量配置模型; CCG算法; 线性化处理; MATLAB; Yamilp; CPLEX,微电网鲁棒优化模型:两阶段成本最小化与线性化处理
西门子S7-200PLC在Z35摇臂钻床控制系统中的应用与组态王组态设计研究,98西门子S7-200PLC和组态王组态Z35摇臂钻床控制系统组态设计PLC设计 ,西门子S7-200PLC; 组态王组态; 摇臂钻床控制系统; PLC设计,西门子S7-200PLC与组态王Z35摇臂钻床控制系统组态设计
烟花代码编程python满屏-10.排队接水——我直接把水吸过来.py
基于三菱PLC的喷灌控制系统设计及组态画面实现,No.393 三菱PLC组态王组态画面基于PLC的喷灌控制设计灌溉控制 ,基于三菱PLC; 喷灌控制设计; 组态王组态画面; 灌溉控制。,基于三菱PLC的喷灌控制设计:组态王组态画面应用
基于Dijkstra算法的路径规划Matlab代码:读取黑白色地图并实现图像上的路径规划示例,读取黑白色地图,在图片上进行路径规划matlab代码 路径规划算法基于读图识别的Dijkstra算法 随意设置坐标,规划路径 示例如下 ,读取地图; 路径规划算法; Dijkstra算法; 坐标设置; 规划路径,基于Dijkstra算法的Matlab黑白色地图路径规划代码
融合空间特征的债券图表数据文本检测方法研究.pdf
基于粒子群优化与遗传算法的高速列车横向悬挂模糊PID控制技术研究:s函数建模与仿真分析详解文件,基于粒子群 遗传算法的高速列车横向悬挂模糊PID控制-s函数搭建。 赠word详解文件 ,基于粒子群; 遗传算法; 高速列车横向悬挂; 模糊PID控制; s函数搭建,基于遗传算法的高速列车悬挂PID模糊控制的S函数构建方案
一种基于Retinex的非线性彩色图像增强算法.pdf
基于因式分解的逆合成孔径雷达三维成像技术及序列因子分解法研究,逆合成孔径雷达三维成像,因式分解法,序列因子分解法。 此部分只做了因式分解的工作,假设散射点已经准确提取并得到散射点坐标矩阵,利用因式分解恢复目标三维结构 ,逆合成孔径雷达三维成像; 因式分解法; 序列因子分解; 散射点提取; 散射点坐标矩阵; 恢复目标三维结构。,利用因式分解恢复三维结构:逆合成孔径雷达三维成像技术
MATLAB R2021b环境下深度学习驱动的车道线检测算法研究与应用,MATLAB环境下一种基于深度学习的车道线检测方法 算法运行环境为matlab r2021b,执行基于深度学习的车道线检测。 if batch ~= numBatches lastFrameIdx = miniBatchSize*batch; else 压缩包=数据+程序 ,核心关键词如下: MATLAB环境; 深度学习; 车道线检测; 算法运行环境; 批处理; 压缩包 以上关键词用分号分隔为: MATLAB环境; 深度学习; 车道线检测; 算法运行环境r2021b; 批处理(batch~numBatches); 压缩包(数据+程序) 注意:最后一个关键词“压缩包”并不是直接从您提供的信息中提炼出来的,而是根据您提到的“压缩包=数据+程序”这一句推断出来的。如果这不是您想要的核心关键词,请告诉我,我会进行相应的调整。,MATLAB深度学习车道线检测算法压缩包
西门子S7-200PLC在物料自动称量控制系统中的应用:基于称重配料混合程序的组态设计与王设计PLC程序设计,74基西门子S7-200PLC的物料自动称量控制系统称重配料物料混合程序组态设计组态设计组态王设计plc程序设计 ,核心关键词:西门子S7-200PLC;自动称量控制系统;物料混合程序;组态设计;组态王设计;PLC程序设计。,西门子S7-200PLC物料自动称量控制系统称重配料程序组态设计
优化无人机侦查与目标搜索路径规划:对未知区域进行覆盖并精确寻靶的Matlab代码解析与实践指南。,无人机覆盖搜索路径规划 无人机搜索目标路径规划 无人机侦查路径规划 对未知区域进行覆盖搜索,并且寻找目标 matlab代码有详细注释,可快速上手。 ,核心关键词:无人机; 覆盖搜索路径规划; 搜索目标路径规划; 侦查路径规划; 未知区域覆盖搜索; MATLAB代码注释。,**无人机未知区域覆盖搜索及目标路径规划Matlab代码详解**
shp格式,可直接导入arcgis使用
基于博途软件编程的11层电梯控制系统:文档齐全,优质售后保障的智能运行体验,基于PLC的单部11层电梯控制系统,采用博途软件编写提供画面,文档(含接线图,流程图,IO分配表)及优质的后服务。 最终运行效果,详见上方演示视频 ,核心关键词:PLC控制;11层电梯;博途软件;画面编写;文档资料;接线图;流程图;IO分配表;售后服务;演示视频。,"博途软件控制下的11层电梯系统,高效运行效果详见演示视频"
"飞剪追剪程序:PLC与伺服同步控制完整指南,适合新手学习与参考,包含PLC程序、触摸屏程序及CAD电路图纸",飞剪追剪程序plc程序伺服程序 同步控制 适合新手学习参考 包含PLC程序+触摸屏程序+CAD电路图纸。 ,飞剪追剪程序; PLC程序; 伺服程序; 同步控制; 新手学习参考; PLC程序+触摸屏程序; CAD电路图纸,适合新手的飞剪追剪程序全套教程:PLC+伺服同步控制
使用Matlab编程:无迹卡尔曼滤波算法(UKF)的编写及其在电池SOC估计中的应用,噪声系数自适应优化方案的研究。,使用matlab编写m脚本,编写无迹卡尔曼滤波算法(UKF)估计电池SOC,注释清晰。 卡尔曼滤波算法(EKF)锂电池SOC估计,噪声系数自适应 Matlab ,matlab; 无迹卡尔曼滤波算法(UKF); 电池SOC估计; 注释清晰; 噪声系数自适应。,Matlab无迹卡尔曼滤波(UKF)用于电池SOC估计的代码实现
Ansys LS-DYNA多孔延时起爆与重复起爆模拟的完整过程解析,Ansys ls_dyna多孔延时起爆,重复起爆模拟 全过程 ,Ansys;LS_dyna;多孔延时起爆;重复起爆模拟;全过程,Ansys LS-DYNA多孔延时重复起爆模拟全过程
FPGA驱动双目视觉系统:立体匹配、视差图与深度图生成技术的研究与应用,FPGA双目视觉 立体视觉 视差图 深度图 双目立体匹配sgm sgbm tang 20k 高云fpga usb摄像头采集图像 ,FPGA双目视觉;立体视觉;视差图;深度图;双目立体匹配sgm;sgbm;高云FPGA;USB摄像头图像采集。,基于FPGA的双目视觉系统:立体匹配与深度图生成
整个手套大盘的指数图如下.docx