首页 > 其他分享 >使用opencvjs提取图片中的红色印章

使用opencvjs提取图片中的红色印章

时间:2024-10-26 21:58:21浏览次数:6  
标签:提取 Mat dst 印章 let opencvjs new cv rect

首先看下效果:

首先对于纯红色的印章提取,也就是通过提取红色 的像素然后得到印章的结果,然后通过在红色的图像中寻找圆圈检测来进行圈定印章的位置
源码位置:https://github.com/xxss0903/extractstamp

  • 第一步是提取红色内容
function extractStampWithColorToOpencvMat(
    img,
    setColor = "#ff0000"
) {
  if (cvReady) {
    // 获取图片的宽高
    const imgWidth = img.width;
    const imgHeight = img.height;
    console.log("图片宽度:", imgWidth, "图片高度:", imgHeight);
    let src = cv.imread(img);
    let dst = new cv.Mat();
    let mask = new cv.Mat();

    // 转换为HSV颜色空间
    cv.cvtColor(src, dst, cv.COLOR_RGBA2RGB);
    cv.cvtColor(dst, dst, cv.COLOR_RGB2HSV);

    // 定义红色的HSV范围
    // 低值范围 (0-10)
    let lowRedA = new cv.Mat(dst.rows, dst.cols, dst.type(), [0, 50, 50, 0]);
    let highRedA = new cv.Mat(dst.rows, dst.cols, dst.type(), [10, 255, 255, 255]);

    // 高值范围 (170-180)
    let lowRedB = new cv.Mat(dst.rows, dst.cols, dst.type(), [170, 50, 50, 0]);
    let highRedB = new cv.Mat(dst.rows, dst.cols, dst.type(), [180, 255, 255, 255]);

    // 创建掩码
    let maskA = new cv.Mat();
    let maskB = new cv.Mat();
    cv.inRange(dst, lowRedA, highRedA, maskA);
    cv.inRange(dst, lowRedB, highRedB, maskB);

    // 合并掩码
    cv.add(maskA, maskB, mask);

    // 将十六进制颜色值转换为RGBA
    const dstColor = hexToRgba(setColor);
    console.log("dstColor:", dstColor);

    // 创建带有 alpha 通道的目标图像
    let result = new cv.Mat(src.rows, src.cols, cv.CV_8UC4, [0, 0, 0, 0]);

    // 创建指定颜色的图像(带有 alpha 通道)
    let colorMat = new cv.Mat(src.rows, src.cols, cv.CV_8UC4, [
      ...dstColor.slice(0, 3),
      255,
    ]);

    // 使用掩码将提取的区域设置为指定颜色,非提取区域保持透明
    colorMat.copyTo(result, mask);

    // 释放内存
    src.delete();
    dst.delete();
    mask.delete();
    maskA.delete();
    maskB.delete();
    lowRedA.delete();
    highRedA.delete();
    lowRedB.delete();
    highRedB.delete();
    colorMat.delete();
    return result;
  } else {
    console.error("OpenCV.js 未加载");
    return img;
  }
}
  • 第二步,提取圆形印章,然后裁剪下来
function extractCirclesWithCvMat(cvMat) {
  let dst = new cv.Mat();
  // 转换为灰度图
  cv.cvtColor(cvMat, dst, cv.COLOR_RGBA2GRAY);
  // 应用高斯模糊以减少噪声
  cv.GaussianBlur(dst, dst, new cv.Size(5, 5), 2, 2);
  
  let croppedStamps = [];
  // 检测圆形
  let circles = detectCircles(dst);
  console.log("circles:", circles);
  circles.forEach((circle) => {
    console.log("draw circle:", circle);
    croppedStamps.push(cropAndDownloadCircle(cvMat, circle));
  });
  // 释放内存
  dst.delete();
  
  return croppedStamps;
}
  • 第三步,裁剪圆形印章
function cropAndDownloadCircle(cvMat, circle) {
  // 定义缩放因子,使裁剪范围比圆形大一些
  const scaleFactor = 1.2;
  // 计算新的半径和尺寸
  let newRadius = circle.radius * scaleFactor;
  let size = Math.round(newRadius * 2);

  // 创建一个新的Mat来存储裁剪后的图像
  let croppedMat = new cv.Mat();
  let rect = new cv.Rect(
    Math.round(circle.x - newRadius),
    Math.round(circle.y - newRadius),
    size,
    size
  );

  // 确保裁剪区域在图像范围内
  rect.x = Math.max(0, Math.min(rect.x, cvMat.cols - rect.width));
  rect.y = Math.max(0, Math.min(rect.y, cvMat.rows - rect.height));
  rect.width = Math.min(rect.width, cvMat.cols - rect.x);
  rect.height = Math.min(rect.height, cvMat.rows - rect.y);

  // 裁剪图像
  croppedMat = cvMat.roi(rect);

  // 创建圆形掩码
  let mask = new cv.Mat.zeros(size, size, cv.CV_8UC1);
  let center = new cv.Point(size / 2, size / 2);
  cv.circle(mask, center, Math.round(newRadius), new cv.Scalar(255, 255, 255), -1);

  // 应用掩码
  let result = new cv.Mat();
  cv.bitwise_and(croppedMat, croppedMat, result, mask);

  // 将结果转换为PNG数据URL
  let imgData = new ImageData(new Uint8ClampedArray(result.data), result.cols, result.rows);
  let canvas = document.createElement('canvas');
  canvas.width = result.cols;
  canvas.height = result.rows;
  let ctx = canvas.getContext('2d');
  ctx.putImageData(imgData, 0, 0);
  let dataURL = canvas.toDataURL("image/png");

  // 释放内存
  croppedMat.delete();
  mask.delete();
  result.delete();

  return dataURL;
}

注意需要引入opencv.js,可以在index.html中引入
<script src="https://docs.opencv.org/4.x/opencv.js" type="text/javascript"></script>

标签:提取,Mat,dst,印章,let,opencvjs,new,cv,rect
From: https://www.cnblogs.com/xxss0903/p/18504621

相关文章

  • 寄生参数提取 Parasitic extraction
    在EDA中,寄生参数提取(寄生析出)是在设计设备和电子电路要求的线路相互连接着两者之间的寄生效应的计算,诸如寄生电容、寄生电阻、寄生电感等寄生效应的计算,一般地称之为寄生设备,寄生元件或者简称为寄生参量(寄生效应)。寄生参数提取的主要目的是创建电路的一个精确模拟模型,这样,详细的......
  • 提取路径,只保留数字,并且从大到小排序
    importosimportre#目录路径directory_path='./train'#用于存储提取的数字(作为整数)的列表extracted_numbers=[]#获取目录下的所有文件和子目录名称files_and_dirs=os.listdir(directory_path)#遍历文件和子目录名称fornameinfiles_and_dirs:#......
  • 使用livox mid 70提取特征点过程
    参考链接使用rviz显示bag数据LOAM-Preprocessingloam_livox实现第一版读了一下驱动程序说明书创建了ros环境,创建了demo功能包,创建了类,订阅话题"/livox/lidar"激光雷达数据,不处理直接发布,发布话题"/full"在rviz中查看。说明书首先,览沃ROS驱动程序可以看到广播码说明......
  • 使用Llama Index与Streamlit实现一个从文本中提取专业术语和定义网页小程序
    LlamaIndex有很多文档完备的用例(语义搜索、摘要等)。然而,这并不意味着我们不能将LlamaIndex应用到非常具体的用例中!在本教程中,我们将介绍使用LlamaIndex从文本中提取术语和定义的设计过程,同时允许用户稍后查询这些术语。使用Streamlit,我们可以提供一种简单的方法来构建用......
  • 将NC栅格表示时间维度的数据提取出来的方法
      本文介绍基于Python语言,逐一读取大量.nc格式的多时相栅格文件,导出其中所具有的全部时间信息的方法。  .nc是NetCDF(NetworkCommonDataForm)文件的扩展名,表示一种常用的科学数据存储格式。NetCDF是一种自描述的、可移植的二进制文件格式,用于存储科学和工程领域的大型数据集......
  • Python 在Excel中插入、替换、提取、或删除图片
    Excel是主要用于处理表格和数据的工具,我们也能在其中插入、编辑或管理图片,为工作表增添视觉效果,提升报告的吸引力。本文将详细介绍如何使用Python操作Excel中的图片,包含以下4个基础示例:Python在Excel中插入图片Python替换Excel中的图片Python提取Excel中的图片Python删除......
  • 怎么提取PDF文件中的文字内容–免费工具分享
    序言目前市面上有关pdf处理的工具有很多,不过绝大多数的PDF处理工具都需要付费使用,且很多厂商甚至连试用的机会也不给用户,有试用的,也是限制在几页内,这样就导致用户还没有办法确认你的软件是否满足需要,就要先付费购买会员或者授权,跟强买强卖有什么区别? 96缔盟pdf版式文件处理......
  • 提取并排序数组中的偶数
    题目:提取并排序数组中的偶数题目描述:给定一个整数n和一个包含n个整数的数组,编写一个程序提取数组中的所有偶数,并按升序排序后输出。输入格式:第一行包含一个整数 n (1≤ n ≤100,000),表示数组的元素个数。第二行包含 n 个整数,表示数组中的元素。每个整数的绝对......
  • WebRTC学习五:从视频中提取图片
    系列文章目录第一篇基于SRS的WebRTC环境搭建第二篇基于SRS实现RTSP接入与WebRTC播放第三篇centos下基于ZLMediaKit的WebRTC环境搭建第四篇WebRTC学习一:获取音频和视频设备第五篇WebRTC学习二:WebRTC音视频数据采集第六篇WebRTC学习三:WebRTC音视频约束第七......
  • Unity引擎CSharp数据加密通用提取方法
    CSharp一般数据加密后解密使用CryptoStream::Read解密,在程序启动时Hook该函数,然后可以截获到解密的数据步骤:Hook引擎mono的函数mono_runtime_invokeAsmHook::HOOK_INFO _mono_runtime_invoke;BOOL__cdeclhook_mono_runtime_invoke(VOID*pUserParam,AsmHook::......