ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 555|回复: 2

[求助] VBA如何处理图像相似度问题求助

[复制链接]

TA的精华主题

TA的得分主题

发表于 2023-7-10 17:54 | 显示全部楼层 |阅读模式
本帖最后由 大氵寿 于 2023-7-10 18:07 编辑

在坛子里找了匹配图片的代码, 但是是直接根据每个像素rgb值去比对,

实际情况里每次像素点渲染可能有极度细微的差异, 导致匹配失败.

有没有什么算法, 能得出2个图片的整体相似度, 比如超过90%就认为找到了这个图.

  1. Option Explicit
  2. Private Declare PtrSafe Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long


  3. '====================================================
  4. Private Declare PtrSafe Function GetDIBits Lib "gdi32" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
  5. Private Declare PtrSafe Function SetDIBits Lib "gdi32" (ByVal hdc As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
  6. '====================================================
  7. Private Declare PtrSafe Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
  8. '左键单击
  9. '====================================================
  10. Private Declare PtrSafe Function GetDC Lib "user32" (ByVal hwnd As Long) As Long    '获取句柄
  11. Private Declare PtrSafe Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long    '获取图片数据
  12. Private Declare PtrSafe Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long    '释放DC
  13. Private Declare PtrSafe Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
  14. Private Declare PtrSafe Function CreateCompatibleBitmap Lib "gdi32" (ByVal hdc As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long
  15. Private Declare PtrSafe Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long
  16. Private Declare PtrSafe Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
  17. Private Declare PtrSafe Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
  18. Private Const SRCCOPY = &HCC0020    ' (DWORD) dest = source
  19. Private Type POINTAPI '定义点(Point)结构
  20. x As Long '点在X坐标(横坐标)上的坐标值
  21. y As Long '点在Y坐标(纵坐标)上的坐标值
  22. End Type

  23. Public intX As Long
  24. Public intY As Long
  25. '颜色表
  26. Private Type RGBQUAD
  27.     rgbBlue As Byte
  28.     rgbGreen As Byte
  29.     rgbRed As Byte
  30.     rgbAlpha As Byte   '透明通道
  31. End Type
  32. Private Type bitmap
  33.     bmType   As Long
  34.     bmWidth   As Long
  35.     bmHeight   As Long
  36.     bmWidthBytes   As Long
  37.     bmPlanes   As Integer
  38.     bmBitsPixel   As Integer
  39.     bmBits   As Long
  40. End Type

  41. Private Type BITMAPINFOHEADER
  42.     biSize As Long          '位图大小
  43.     biWidth As Long
  44.     biHeight As Long
  45.     biPlanes As Integer
  46.     biBitCount As Integer   '信息头长度
  47.     biCompression As Long   '压缩方式
  48.     biSizeImage As Long
  49.     biXPelsPerMeter As Long
  50.     biYPelsPerMeter As Long
  51.     biClrUsed As Long
  52.     biClrImportant As Long
  53. End Type
  54. Private Type BITMAPINFO
  55.     bmiHeader As BITMAPINFOHEADER
  56.     bmiColors As RGBQUAD
  57. End Type
  58. '图片文件头
  59. Private Const DIB_RGB_COLORS = 0    '  color table in RGBs
  60. Dim BI As BITMAPINFO
  61. Dim BI1 As BITMAPINFO
  62. Private Const HIMETRIC_PER_PIXEL = 96 / 2540
  63. Private Const vbPicTypeBitmap = 1
  64. Private Enum EnumPicMode
  65.     BlackWhite = 0
  66.     GrayScale = 1
  67. End Enum

  68. Public Function FindPic(Left As Long, Top As Long, Right As Long, Bottom As Long, fileurl As String) As Boolean
  69.     Dim PicSrc As StdPicture
  70.     Dim ix As Integer
  71.     Dim iy As Integer
  72.     Dim iWidth As Integer    '以像素为单位的图形宽度
  73.     Dim iHeight As Integer    '以像素为单位的图形高度
  74.     Dim bytTarget As Byte
  75.     Dim hdc As Long, hDCmem As Long
  76.     Dim hBmp As Long, hBmpPrev As Long
  77.     Dim bits2()
  78.     Dim bits() As Byte    '三维数组,用于获取原彩色图像中各像素的RGB数值以及存放转化后的灰度值
  79.     Dim bitsBW() As Byte    '三维数组,用于存放转化为黑白图后各像素的值
  80.     Dim lrtn, w, h, paths
  81.     paths = ThisWorkbook.Path & "\pics" & fileurl
  82.      UserForm1.Image1.Picture = LoadPicture(paths)
  83.     Set PicSrc = UserForm1.Image1.Picture
  84.     '获取图形的宽度和高度
  85.     iWidth = PicSrc.Width * HIMETRIC_PER_PIXEL
  86.     iHeight = PicSrc.Height * HIMETRIC_PER_PIXEL

  87.     '创建并初始化一个bitMapInfo自定义类型
  88.     Dim bi24BitInfo As BITMAPINFO
  89.     With bi24BitInfo.bmiHeader
  90.         .biBitCount = 32
  91.         .biCompression = 0&
  92.         .biPlanes = 1
  93.         .biSize = Len(bi24BitInfo.bmiHeader)
  94.         .biWidth = iWidth
  95.         .biHeight = iHeight
  96.     End With
  97.   
  98.     '重新定义数组大小
  99.     ReDim bits(0 To 3, 0 To iWidth - 1, 0 To iHeight - 1) As Byte
  100.     hdc = GetDC(0)
  101.     hDCmem = CreateCompatibleDC(hdc)
  102.     '使用GetDIBits方法一次性获取picture1中各点的rgb值,比point方法或getPixel函数逐像素获取像素rgb要快出一个数量级
  103.     lrtn = GetDIBits(hDCmem, PicSrc.Handle, 0&, iHeight, bits(0, 0, 0), bi24BitInfo, DIB_RGB_COLORS)
  104.     '数组的三个维度分别代表像素的RGB分量、以图形左下角为原点的X和Y坐标。
  105.     '具体说来,这时bits(0,2,3)代表从图形左下角数起横向第2个纵向第3个像素的Blue值,而bits(1,2,3)和bits(2,2,3)分别的Green值和Red值.
  106.     ReleaseDC 0, hdc

  107.     w = Right
  108.     h = Bottom
  109.     With BI1.bmiHeader
  110.         .biSize = Len(BI1.bmiHeader)
  111.         .biWidth = w
  112.         .biHeight = h
  113.         .biBitCount = 32
  114.         .biPlanes = 1
  115.     End With

  116.     Dim hBMPhDC
  117.     Dim hDCmem2 As Long
  118.     Dim Pic1Handle2 As Long
  119.     Dim hBmpPrev2 As Long
  120.     Dim ixx, j, i, i2, j2
  121.     Dim fpic() As Byte
  122.     hBMPhDC = GetDC(0)
  123.     '常规抓图代码,得到一个hBmp:
  124.     hDCmem2 = CreateCompatibleDC(hBMPhDC)
  125.     Pic1Handle2 = CreateCompatibleBitmap(hBMPhDC, Right, Bottom)
  126.     hBmpPrev = SelectObject(hDCmem2, Pic1Handle2)
  127.     BitBlt hDCmem2, 0, 0, Right, Bottom, hBMPhDC, Left, Top, SRCCOPY  'SelectObject hDCmem, hBmpPrev
  128.     ReDim fpic(0 To 3, 0 To w - 1, 0 To h - 1) As Byte

  129.     ixx = GetDIBits(hDCmem2, Pic1Handle2, 0&, h, fpic(0, 0, 0), BI1, 0)
  130.     ReleaseDC 0, hBMPhDC

  131. FindPic = False
  132.     For j = 0 To h - iHeight - 1
  133.         VBA.DoEvents
  134.         For i = 0 To w - iWidth - 1

  135.             For j2 = 0 To iHeight - 1   '循环判断小图片
  136.                 For i2 = 0 To iWidth - 1
复制代码

代码被截断了, 接着:

  1.                     
  2.                     If fpic(2, i + i2, j + j2) < 0.9 * bits(2, i2, j2) Or fpic(2, i + i2, j + j2) > 1.1 * bits(2, i2, j2) Then GoTo ExitLine:    'R
  3.                     If fpic(1, i + i2, j + j2) < 0.9 * bits(1, i2, j2) Or fpic(1, i + i2, j + j2) > 1.1 * bits(1, i2, j2) Then GoTo ExitLine:    'G
  4.                     If fpic(0, i + i2, j + j2) < 0.9 * bits(0, i2, j2) Or fpic(0, i + i2, j + j2) > 1.1 * bits(0, i2, j2) Then GoTo ExitLine:    'B
  5.                     
  6.                 Next i2
  7.             Next j2
  8.                        'Debug.Print "发现:", I, J
  9.             intX = i
  10.             intY = h - j - iHeight
  11.               FindPic = True
  12.           'MoveTo intX, intY
  13.           'MsgBox intX & "" & intY
  14. ExitLine:
  15.         Next i
  16.     Next j

  17. End Function
复制代码


TA的精华主题

TA的得分主题

发表于 2023-7-10 19:12 | 显示全部楼层
比较两张图?你可以用 wia 获取 argb来比较
ARGBData

TA的精华主题

TA的得分主题

发表于 2023-7-11 21:08 | 显示全部楼层
在VBA中处理图像相似度问题,可以借助于图像处理库如OpenCV或EmguCV来实现。以下是一个示例代码,使用EmguCV计算两个图像的相似度。

首先,需要将EmguCV库添加到VBA项目的引用中。可以在工具->引用中选择"Emgu.CV"。

然后,可以使用以下代码来计算两个图像的相似度:

```vba
Sub CalculateImageSimilarity()
    ' 图片路径
    Dim imagePath1 As String
    Dim imagePath2 As String
    imagePath1 = "path to image 1"
    imagePath2 = "path to image 2"
   
    ' 创建图像对象
    Dim img1 As New Emgu.CV.Image(Of Emgu.CV.Structure.Bgr, Byte)(imagePath1)
    Dim img2 As New Emgu.CV.Image(Of Emgu.CV.Structure.Bgr, Byte)(imagePath2)
   
    ' 声明变量保存相似度
    Dim similarity As Double
   
    ' 创建图像比较器
    Dim imageComparer As New Emgu.CV.ImageSimilarity(img1, img2)
   
    ' 计算相似度
    similarity = imageComparer.GetSimilarity()
   
    ' 输出相似度
    MsgBox "相似度: " & similarity
End Sub
```

在上述代码中,替换`imagePath1`和`imagePath2`为你要比较的两个图像的路径。然后通过`Emgu.CV.Image`类创建图像对象。接着,创建`Emgu.CV.ImageSimilarity`对象,传入图像对象。最后,调用`GetSimilarity`方法,返回相似度值。

请注意,这只是一个简单示例,在实际应用中可能需要进行更复杂的图像处理和相似度计算。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-17 00:34 , Processed in 0.029389 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表