C#实现以图搜图

2023-05-16

朋友们,如需转载请标明出处:http://blog.csdn.net/jiangjunshow

 

前言

最近在逛淘宝时发现了淘宝的图片搜索功能,可能是我太Low了这个技术点已经实现很长时间了。想想自己能不能实现这个功能,起初我是这么想的,对两张图片从左上角的第一个像素点一直比较到右下角的最后一个像素点,并在比较时记录它们的相似度,可能是我太天真了(主要还是知识限制了想象),这样做有很多问题,比如说两张图片大小不一致、核心要素点的位置不同等...最终只得借助网络了,找到了一种叫做均值哈希的算法(Average hash algorithm),接下来具体阐述它的基本思路以及适用场景。

均值哈希的基本思路

1、缩小尺寸:

去除图片的高频和细节的最快方法是缩小图片,将图片缩小到8x8的尺寸,总共64个像素。不要保持纵横比,只需将其变成8乘8的正方形。这样就可以比较任意大小的图片,摒弃不同尺寸、比例带来的图片差异。

2、简化色彩:

将8乘8的小图片转换成灰度图像。

3、计算平均值:

计算所有64个像素的灰度平均值。

4、比较像素的灰度:

将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。

5、计算hash值:

将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。

如果图片放大或缩小,或改变纵横比,结果值也不会改变。增加或减少亮度或对比度,或改变颜色,对hash值都不会太大的影响。最大的优点:计算速度快!

那么完成了以上步骤,一张图片就相当于有了自己的"指纹"了,然后就是计算不同位的个数,也就是汉明距离(例如1010001与1011101的汉明举例就是2,也就是不同的个数)。

如果汉明距离小于5,则表示有些不同,但比较相近,如果汉明距离大于10则表明完全不同的图片。

以上就是均值哈希的基本实现思路,总体来说是比较简单的。

C#实现

public class ImageHashHelper
{
    /// <summary>
    /// 获取缩略图
    /// </summary>
    /// <returns></returns>
    private static Bitmap GetThumbImage(Image image, int w, int h)
    {
        Bitmap bitmap = new Bitmap(w, h);
        Graphics g = Graphics.FromImage(bitmap);
        g.DrawImage(image,
            new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            new Rectangle(0, 0, image.Width, image.Height), GraphicsUnit.Pixel);
        return bitmap;
    }

    /// <summary>
    /// 将图片转换为灰度图像
    /// </summary>
    /// <returns></returns>
    private static Bitmap ToGray(Bitmap bmp)
    {
        for (int i = 0; i < bmp.Width; i++)
        {
            for (int j = 0; j < bmp.Height; j++)
            {
                //获取该点的像素的RGB的颜色
                Color color = bmp.GetPixel(i, j);
                //利用公式计算灰度值
                int gray = (int)(color.R * 0.3 + color.G * 0.59 + color.B * 0.11);//计算方式1
                //int gray1 = (int)((color.R + color.G + color.B) / 3.0M);//计算方式2
                Color newColor = Color.FromArgb(gray, gray, gray);
                bmp.SetPixel(i, j, newColor);
            }
        }
        return bmp;
    }

    /// <summary>
    /// 获取图片的均值哈希
    /// </summary>
    /// <returns></returns>
    public static int[] GetAvgHash(Bitmap bitmap)
    {
        Bitmap newBitmap = ToGray(GetThumbImage(bitmap, 8, 8));
        int[] code = new int[64];
        //计算所有64个像素的灰度平均值。
        List<int> allGray = new List<int>();
        for (int row = 0; row < bitmap.Width; row++)
        {
            for (int col = 0; col < bitmap.Height; col++)
            {
                allGray.Add(newBitmap.GetPixel(row, col).R);
            }
        }
        double avg = allGray.Average(a => a);//拿到平均值
        //比较像素的灰度
        for (int i = 0; i < allGray.Count; i++)
        {
            code[i] = allGray[i] >= avg ? 1 : 0;//将比较结果进行组合
        }
        //返回结果
        return code;
    }

    /// <summary>
    /// 对两个AvgHash进行比较
    /// </summary>
    /// <returns></returns>
    public static int Compare(int[] code1, int[] code2)
    {
        int v = 0;
        for (int i = 0; i < 64; i++)
        {
            if (code1[i] == code2[i])
            {
                v++;
            }
        }
        return v;
    }
}
复制代码

这里我们在GetAvgHash函数中获取64个像素的灰度值时直接通过了R来获取,因为RGB都是一样的,所以哪一个都可以。

灰度值换算:baike.baidu.com/item/灰度值/10…

效果演示:

1、原图查找

 

 

 

2、完全马赛克查找

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#实现以图搜图 的相关文章

随机推荐

  • GBK编码表

    全国信息技术标准化技术委员会 汉字内码扩展规范 GBK Chinese Internal Code Specification 1 0 版 xff08 按编码顺序排列 xff09 其编码范围 xff1a 8140 xff0d FEFE xf
  • dll文件下载网址

    https cn dll files com
  • windows中dos命令汇总及获取管理员权限

    文章目录 windows 获取管理员权限的2种方式runas 用法 windows dos 命令行语法项windows dos命令总述 windows dos命令详细介绍 win7及以前 微软官网 windows dos命令详细介绍 win
  • windows比cmd更强大的 WMIC命令使用详解

    文章目录 什么是wmic WMIC能做什么 WMIC命令使用帮助文档WMIC命令使用实例wmic的运行方式可以有两种法1 显示进程的详细信息2 停止 暂停和运行服务功能3 显示出BIOS信息4 停止进程的操作5 连接远程电脑6 BIOS 基
  • 编程意识——宏定义封装多个函数参数

    作者 釜薪君 公众号 嵌入式杂牌军 文章目录 前言一 这种意识的来源二 实现源码分析1 函数调用2 宏定义部分3 函数实现4 宏替换后的函数调用 总结 前言 今天带小伙伴们分析一段不错的代码 xff0c 学习一下关于宏封装的一种意识 xff
  • DSP28335的SCI的FIFO中断使用心得

    自学了一段时间的DSP28335的串口设置 xff0c 写下来帮助更多的新手 xff0c 遇到了很多问题也记录一些解决办法 以下全都是我个人的理解 xff0c 可能说的不对 xff0c 大家讨论 1 关于为什么必须用FIFO 一般的DSP系
  • 51单片机堆栈深入剖析

    用C语言进行MCS51系列单片机程序设计是单片机开发和应用的必然趋势 Keil公司的C51编译器支持经典8051和8051派生产品的版本 xff0c 通称为Cx51 应该说 xff0c Cx51是C语言在MCS51单片机上的扩展 xff0c
  • 基于ros_arduino_bridge的智能小车----上位机篇

    基于ros arduino bridge的智能小车 上位机篇 基于ros arduino bridge的智能小车 硬件篇 基于ros arduino bridge的智能小车 下位机篇 ros arduino bridge文件系统 xff08
  • 基于ros_arduino_bridge的智能小车----下位机篇

    基于ros arduino bridge的智能小车 下位机篇 参考文章 xff1a 基于ros arduino bridge的智能小车 上位机篇 基于ros arduino bridge的智能小车 硬件篇 下位机部分实际上可以视作完全独立的
  • 【命令】Python执行命令超时控制【原创】

    目录 参考 概要 方案 方案一 xff1a os system 方案二 xff1a os popen 方案三 xff1a subprocess check output 方案四 xff1a subprocess Popen 方案五 xff1
  • nRF52 Mesh开发 (2) SDK例程Light_switch server 添加一个element控制开发板其他LED灯

    server文件结构 xff1a 使用SEGGER编译的话直接打开 emProject文件即可 xff1b img文件中包含程序运行过程图 xff1b include文件包含该例程下的头文件 xff1b 2 具体操作 xff1a 在main
  • nRF52 Mesh开发 (3) MESH Sensor Server/Client Models详解与实现

    MESH Sensor Model 实现 MESH Spec规定的 Sensor Model 标准传感器状态传感器描述传感器参数设置传感器cadence传感器数据 传感器可发送和接收的消息Sensor Server Client Model
  • Telink Mesh 开发(1)调试log打印

    Telink Mesh SDK 调试log打印 Telink 官网论坛建议使用GPIO模拟串口打印log xff0c 推荐阅读Telink官网发布的最新SDK使用手册 xff0c 更新了不少东西 一 使用串口打印log1 使能uart lo
  • 蓝牙Mesh基础(3)蓝牙Mesh协议--总览

    蓝牙Mesh协议 总览Bearer Layer xff08 承载层 xff09 Network Layer xff08 网络层 xff09 Low Transport Layer xff08 下层传输层 xff09 Upper Transp
  • 蓝牙Mesh基础(9)设备配网

    设备配网 xff08 启动配置 xff09 设备配网过程配网PDU配网PDU如何传输呢 设备配网过程 首先 xff0c 需要配网的设备先进行未配网广播 xff0c 这个广播不同于普通的ble广播 xff0c 广播数据结构类型 xff08 A
  • 弱网络环境模拟--树莓派搭建ATC

    弱网络环境模拟 树莓派搭建ATC 1 硬件和系统2 搭建过程3 遇到的问题1 Failed to start hostapd service Unit hostapd service is masked2 django python版本问题
  • OpenCV双目相机测距程序

    本文主要分享一个双目测距的实现程序 xff0c 用的bumblebee2相机 使用的OpenCV自带的BM算法 在OpenCV3中 xff0c StereoBM算法发生了比较大的变化 xff0c StereoBM被定义为纯虚类 xff0c
  • stm32 printf 串口输出

    在使用STM32调试时 xff0c 经常使用串口发送信息 xff0c 为了方便调试与串口发送信息 xff0c 用printf xff08 xff09 函数实现通过串口打印信息 1 添加包含printf xff08 xff09 函数的头文件
  • 【slighttpd】基于lighttpd架构的Server项目实战(7)—http-parser

    对于http服务器 xff0c http request的解析是比较麻烦的 xff0c 由于我们的重点并不在这上面 xff0c 所以这一部分不打算自己编写 xff0c 而是使用开源的http parser库 xff0c 下面我们将使用该库来
  • C#实现以图搜图

    朋友们 xff0c 如需转载请标明出处 xff1a http blog csdn net jiangjunshow 前言 最近在逛淘宝时发现了淘宝的图片搜索功能 xff0c 可能是我太Low了这个技术点已经实现很长时间了 想想自己能不能实现