关于名片全能王扫描,返回切边增强图片web api的图片数据分割

本文介绍了一种处理WebAPI返回的VCF文件的方法,重点在于如何正确读取VCF文件中的文本信息,并将文件末尾的图片数据保存为独立的图片文件。

这个web api的接口是返回一个vcf的文件,文件中以END:VCARD和“\r\n”为结束符,后面的数据到文件末尾就是图片数据

首先,要以END:VCARD为结束符,就只能从中读取字符进行匹配,因为可能包含中文,所以我们暂且用read(char[])或者readLine()方法来实现,这样读出来的就是以字符或者整行为单位的,但是后面的数据要以byte的形式写入到图片文件中,所以这里我将输入流的数据copy了一份,具体见代码

try {
			url = new URL(strUrl);
			HttpURLConnection connection = (HttpURLConnection) url
					.openConnection();
			connection.setDoOutput(true);// post请求,需要向服务器写数据
			connection.setDoInput(true);// 因为要从服务器端获取响应数据,所以为true(默认值也是true)
			connection.setRequestMethod("POST");
			connection.setRequestProperty("Content-Type","multipart/form-data; boundary=" + boundary);

			OutputStream outputStream = new DataOutputStream(
					connection.getOutputStream());
			// write first boundary
			outputStream.write(("--" + boundary + "\r\n").getBytes());
			// for(Map.Entry<String, String> entry : params.entrySet()) {
			// outputStream.write(("Content-Disposition: from-data; name=\""
			// +entry.getKey()+ "\"\r\n\r\n").getBytes());
			// outputStream.write(entry.getValue().getBytes());
			// outputStream.write(("\r\n--" + boundary + "\r\n").getBytes());
			// }
			outputStream
					.write(("Content-Disposition: form-data; name=\"upfile\"; filename=\""
							+ fileName + "\"\r\n").getBytes());
			outputStream.write(("Content-type: application/octet-stream\r\n")
					.getBytes());
			outputStream.write("Content-Transfer-Encoding: binary\r\n\r\n"
					.getBytes());

			byte[] buffer = new byte[4096];
			int length = 0;
			while ((length = fileInputStream.read(buffer)) != -1) {
				outputStream.write(buffer, 0, length);
			}
			// write last boundary
			outputStream.write(("\r\n--" + boundary + "--\r\n").getBytes());
			outputStream.flush();
			outputStream.close();
			fileInputStream.close();

			if (200 == connection.getResponseCode()) {
				// 将图片数据结果写入到baos流中
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				// 保存图片信息
				FileOutputStream fos = null;
				if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
					fos = new FileOutputStream(Environment
							.getExternalStorageDirectory().getPath()
							+ "/DCIM/result.jpg");
				} else {
					fos = new FileOutputStream(Environment.getDataDirectory()
							.getPath() + "/sdcard/DCIM/Camera/result.jpg");
				}
				
				// 先将数据放入缓冲区,然后read的时候再冲缓冲区中取出数据(inputstream流的copy)
				BufferedInputStream bis = new BufferedInputStream(connection.getInputStream());
				//先将inputstream中的数据全部读取到totalBaos输出流中
				ByteArrayOutputStream totalBaos = new ByteArrayOutputStream();
				byte[] totalBuffer = new byte[4096];
				int l = 0;
				while((l = bis.read(totalBuffer)) != -1) {
					totalBaos.write(totalBuffer, 0, l);
				}
				totalBaos.flush();
				bis.close();
				
				//读取名片扫描的结果,文字部分
				BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(totalBaos.toByteArray())));
				StringBuffer strVcf = new StringBuffer();
				String strTemp ;
				while ((strTemp = br.readLine()) != null) {
					strVcf.append(strTemp).append("\r\n");
					if ( strVcf.toString().contains("END:VCARD")) {
						Log.d("MainActivity", "strVcf length: "
								+ strVcf.toString().getBytes().length + "");
						// 当遇到结尾换行符时,同时整个串里面已经包含END:VCARD(之后的就是图片数据)
						break;
					}
				}
				br.close();
				//写图片数据
				byte[] picBuffer = new byte[2048];
				int size = 0;
				int total = 0;
				bis = new BufferedInputStream(new ByteArrayInputStream(totalBaos.toByteArray()));
				bis.skip(strVcf.toString().getBytes().length);//跳过文字部分的流数据
				while ((size = bis.read(picBuffer)) != -1) {
					// 保存图片数据到文件
					fos.write(picBuffer, 0, size);
					// 保存图片数据到baos流
					baos.write(picBuffer, 0, size);
					total += size;
					Log.d("MainActivity", "total:" + total);
				}
				fos.flush();
				fos.close();
				baos.flush();
				baos.close();
				bis.close();
				totalBaos.close();
                            }
                         } catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		        }
希望看到的人,提出自己的解决方法,我的这个方案感觉有点欠妥

实现一个类似“扫描全能王”的图像处理应用程序,主要涉及图像预处理、边缘检测、透视变换等计算机视觉技术。使用 Java 和 OpenCV 可以完成这些任务,并构建一个基本的扫描工具。以下是实现该功能的主要步骤和技术要点: ### 图像预处理 在进行扫描前,需要对输入图像进行预处理,包括灰度化、高斯模糊和边缘增强。这有助于提高后续边缘检测的准确性。 ```java Mat gray = new Mat(); Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY); Mat blurred = new Mat(); Imgproc.GaussianBlur(gray, blurred, new Size(5, 5), 0); ``` ### 边缘检测 使用 Canny 算法检测图像中的边缘,这是识别文档边界的关键步骤。 ```java Mat edges = new Mat(); Imgproc.Canny(blurred, edges, 75, 200); ``` ### 寻找轮廓并筛选最大四边形 通过查找图像中的轮廓,并筛选出最大的四边形区域,通常可以得到文档的边界信息。 ```java List<MatOfPoint> contours = new ArrayList<>(); Mat hierarchy = new Mat(); Imgproc.findContours(edges, contours, hierarchy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); MatOfPoint2f approxCurve = new MatOfPoint2f(); for (MatOfPoint contour : contours) { MatOfPoint2f contour2f = new MatOfPoint2f(contour.toArray()); double peri = Imgproc.arcLength(contour2f, true); Imgproc.approxPolyDP(contour2f, approxCurve, 0.02 * peri, true); if (approxCurve.toList().size() == 4) { // 找到四边形,可能为文档边界 break; } } ``` ### 透视变换 一旦找到文档的四个角点,就可以对其进行透视变换,将文档“展开”成正面视角。 ```java Point[] srcPoints = // 四个角点坐标 Point[] dstPoints = // 目标坐标(如 A4 纸大小) Mat transformMatrix = Imgproc.getPerspectiveTransform(srcPoints, dstPoints); Mat warped = new Mat(); Imgproc.warpPerspective(src, warped, transformMatrix, new Size(500, 600)); ``` ### 显示或保存结果 最后,可以将处理后的图像显示给用户或保存到文件中。 ```java HighGui.imshow("Scanned Document", warped); HighGui.waitKey(); ``` 整个流程中,OpenCV 提供了丰富的图像处理函数,而 Java 作为开发语言则提供了良好的跨平台支持[^1]。虽然这个实现是基础版本,但已经涵盖了扫描应用的核心功能。进一步优化可以通过引入更复杂的图像增强算法、自动裁剪多余背景以及支持多页扫描等功能来提升用户体验[^2]。 ---
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值