


需要使用OpenCV.jar和so文件
android
package com.example.application;
import android.app.Activity;
import android.os.Bundle;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.view.View;
import java.util.ArrayList;
import android.widget.Toast;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.Queue;
import android.graphics.Color;
import java.util.LinkedList;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import org.opencv.android.Utils;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.MatOfPoint;
import java.util.List;
import org.opencv.core.Scalar;
import org.opencv.core.Core;
public class MainActivity extends Activity {
private huabu hb;
private Bitmap bitmap;
static {
// 加载OpenCV的.so库(库名与文件前缀一致,libopencv_java4.so对应"opencv_java4")
System.loadLibrary("opencv_java4");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
hb = findViewById(R.id.huabu);
if (!OpenCVLoader.initDebug()) {
Toast.makeText(this, "OpenCV初始化失败", Toast.LENGTH_SHORT).show();
}
String str="/storage/emulated/0/脚本/Aj图片/screenshot_1759871209890.png";
bitmap = BitmapFactory.decodeFile(str);
}
public void huiduhua(View v) {
processImage();
}
private void processImage() {
// 这里假设你要处理的图片在手机存储的指定路径,替换为实际图片路径
if (bitmap == null) {
Toast.makeText(this, "无法读取图片", Toast.LENGTH_SHORT).show();
return;
}
Mat mat = new Mat();
Utils.bitmapToMat(bitmap, mat);
Mat grayMat = new Mat();
Imgproc.cvtColor(mat, grayMat, Imgproc.COLOR_BGR2GRAY);
Bitmap grayBitmap = Bitmap.createBitmap(grayMat.cols(), grayMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(grayMat, grayBitmap);
hb.setbittmap(grayBitmap);
}
public void hualunkuo(View v) {
//boolean a=colors.isSimilar("#000000", "#000010", 25);
detectBlackFonts();
}
// 识别黑色字体的核心方法
private void detectBlackFonts() {
Bitmap originalBitmap = this.bitmap;
if (originalBitmap == null) {
Toast.makeText(this, "图片读取失败", Toast.LENGTH_SHORT).show();
return;
}
Mat srcMat = new Mat();
Utils.bitmapToMat(originalBitmap, srcMat);
// 处理透明通道
if (srcMat.channels() == 4) {
Imgproc.cvtColor(srcMat, srcMat, Imgproc.COLOR_RGBA2BGR);
}
// 转为灰度图
Mat grayMat = new Mat();
Imgproc.cvtColor(srcMat, grayMat, Imgproc.COLOR_BGR2GRAY);
// 阈值化(突出黑色字体)
Mat binaryMat = new Mat();
Imgproc.threshold(grayMat, binaryMat, 150, 255, Imgproc.THRESH_BINARY_INV);
// 形态学操作:连接笔画
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new org.opencv.core.Size(4, 5));
Imgproc.dilate(binaryMat, binaryMat, kernel);
Imgproc.erode(binaryMat, binaryMat, kernel);
// 提取所有轮廓
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Imgproc.findContours(binaryMat, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
// 过滤有效轮廓并绘制边界矩形
Scalar red = new Scalar(0, 0, 255); // 红色矩形
for (MatOfPoint contour : contours) {
// 1. 计算轮廓面积,过滤过小轮廓
double area = Imgproc.contourArea(contour);
if (area < 50) {
contour.release();
continue;
}
// 2. 获取轮廓的边界矩形(左上角和右下角坐标)
org.opencv.core.Rect rect = Imgproc.boundingRect(contour);
int width = rect.width;
int height = rect.height;
// 3. 过滤宽高比异常的矩形
if (width == 0 || height == 0) {
contour.release();
continue;
}
double ratio = (double) width / height;
if (ratio < 0.2 || ratio > 3.2) {
contour.release();
continue;
}
// 4. 绘制边界矩形(左上角(x1,y1),右下角(x2,y2))
Imgproc.rectangle(
srcMat,
new org.opencv.core.Point(rect.x, rect.y), // 左上角坐标
new org.opencv.core.Point(rect.x + width, rect.y + height), // 右下角坐标
red, // 颜色
2 // 线宽
);
contour.release(); // 及时释放资源
}
Toast.makeText(this, "完成"+contours.size(), 0).show();
// 转换为Bitmap显示
Mat resultMat = new Mat();
Imgproc.cvtColor(srcMat, resultMat, Imgproc.COLOR_BGR2RGBA);
Bitmap resultBitmap = Bitmap.createBitmap(resultMat.cols(), resultMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(resultMat, resultBitmap);
hb.setbittmap(resultBitmap);
// 释放剩余资源
srcMat.release();
grayMat.release();
binaryMat.release();
hierarchy.release();
kernel.release();
resultMat.release();
}
private void log(Exception e) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(baos));
String str = baos.toString();
log(str);
}
public Boolean log(String strcontent) {
try {
strcontent += "\n";
String filePath="/sdcard/log.txt";
File file=new File(filePath);//路径
if (!file.exists()) {
file.getParentFile().mkdirs();
file.createNewFile();//创建txt文件
}
RandomAccessFile raf=new RandomAccessFile(file, "rwd");
raf.seek(file.length());
raf.write(strcontent.getBytes());
raf.close();
return true;
} catch (Exception e) {
}
return false;
}
}