三种方法检测:“热狗还是不是热狗”(OpenCV+Cascades+Hash)+ 爬虫(下载训练集)

本文主要是介绍三种方法检测:“热狗还是不是热狗”(OpenCV+Cascades+Hash)+ 爬虫(下载训练集),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

三种方法检测:“热狗还是不是热狗”(OpenCV+Cascades+Hash)+ 爬虫(下载训练集)

所有代码请到我的github中下载,欢迎star,谢谢。

https://github.com/sileixinhua/HotdogOrNotHotdog

前言

在美剧《硅谷》中国,有一个华裔的演员,演绎了一个普通开发者的故事,做了一个识别热狗的APP,然后被大公司收购用来做色情识别。

这里写图片描述

APP的效果图如下图所示:

这里写图片描述

那今天我就展示用
1.原始的Hash的图像处理方法
2.用OpenCV+numpy一张照片作为正面数据的方法
3.用OpenCV的Cascades方法

来检测热狗,我们就叫它“热狗还是不是热狗”,HotdogOrNotHotdog。

开发环境

windows10

Python3.5

https://www.python.org/downloads/

这里写图片描述

OpenCV-Python

OpenCV的window安装直接官网https://opencv.org/下载源码,把bin路径添加到系如变量即可

在Ubuntu上的安装比较繁琐,我找到的最简单的方式是:

https://www.youtube.com/watch?v=2Pboq2LFoaI

http://www.daslhub.org/unlv/wiki/doku.php?id=opencv_install_ubuntu

整个过程安装比较耗时,大概一刻钟左右。

在Python中安装OpenCV开发包需要如下命令:

pip3 install opencv-python

这里如果是Python2就把“pip3”改成“pip”即可。

如果只用Python的话可以不用下载源码安装,直接pip安装opencv-python即可。

numpy

https://docs.scipy.org/doc/numpy-dev/user/quickstart.html

安装numpy使用下列命令,pip安装

pip3 install numpy

这里写图片描述

matplotlib

https://matplotlib.org/

安装numpy使用下列命令,pip安装

pip3 install matplotlib

这里写图片描述

第一部分:用Hash方法检测

实验步骤设计

首先下载百度图片里的图片,搜索关键字为热狗。

用OpenCV来读取图片内容,用numpy来将图片数据数组化并挨个对比分析图像灰度图的直方图

这里用到的验证算法是汉明距离

代码分析

DownLoadImages.py

# -*- coding:utf-8 -*-  
# coder:橘子派_司磊
# 2017年10月30日 23点58分
# 下载百度图片里的图片,搜索关键字为热狗
import os
import re
import urllib
import json
import socket
import urllib.request
import urllib.parse
import urllib.error
import time# 设置延迟时间
timeout = 5
socket.setdefaulttimeout(timeout)class Crawler:__time_sleep = 0.1__amount = 0__start_amount = 0__counter = 0headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0'}def __init__(self, t=0.1):self.time_sleep = tdef __save_image(self, rsp_data, word):if not os.path.exists("./" + word):os.mkdir("./" + word)self.__counter = len(os.listdir('./' + word)) + 1for image_info in rsp_data['imgs']:try:time.sleep(self.time_sleep)fix = self.__get_suffix(image_info['objURL'])urllib.request.urlretrieve(image_info['objURL'], './' + word + '/' + str(self.__counter) + str(fix))except urllib.error.HTTPError as urllib_err:print(urllib_err)continueexcept Exception as err:time.sleep(1)print(err)print("产生未知错误,放弃保存")continueelse:print("已有" + str(self.__counter) + "张图")self.__counter += 1return@staticmethoddef __get_suffix(name):m = re.search(r'\.[^\.]*$', name)if m.group(0) and len(m.group(0)) <= 5:return m.group(0)else:return '.jpeg'@staticmethoddef __get_prefix(name):return name[:name.find('.')]def __get_images(self, word='火锅'):search = urllib.parse.quote(word)pn = self.__start_amountwhile pn < self.__amount:url = 'http://image.baidu.com/search/avatarjson?tn=resultjsonavatarnew&ie=utf-8&word=' + search + '&cg=girl&pn=' + str(pn) + '&rn=60&itg=0&z=0&fr=&width=&height=&lm=-1&ic=0&s=0&st=-1&gsm=1e0000001e'try:time.sleep(self.time_sleep)req = urllib.request.Request(url=url, headers=self.headers)page = urllib.request.urlopen(req)rsp = page.read().decode('unicode_escape')except UnicodeDecodeError as e:print(e)print('-----UnicodeDecodeErrorurl:', url)except urllib.error.URLError as e:print(e)print("-----urlErrorurl:", url)except socket.timeout as e:print(e)print("-----socket timout:", url)else:rsp_data = json.loads(rsp)self.__save_image(rsp_data, word)print("下载下一页")pn += 60finally:page.close()print("下载任务结束")returndef start(self, word, spider_page_num=1, start_page=1):self.__start_amount = (start_page - 1) * 60self.__amount = spider_page_num * 60 + self.__start_amountself.__get_images(word)if __name__ == '__main__':crawler = Crawler(0.05)crawler.start('火锅', 5000, 1)

ClassificationBypHash.py

# -*- coding:utf-8 -*-  
# coder:橘子派_司磊
# 2017年10月31日 时间
# 用OpenCV来识别图片是否是热狗
# 热狗图片一共11582张
# 火锅照片一共1043张
# 效果十分不理想!!import cv2
import numpy as np # 计算单通道的直方图的相似值 
def calculate(image1,image2): hist1 = cv2.calcHist([image1],[0],None,[256],[0.0,255.0]) hist2 = cv2.calcHist([image2],[0],None,[256],[0.0,255.0]) # 计算直方图的重合度 degree = 0for i in range(len(hist1)): if hist1[i] != hist2[i]: degree = degree + (1 - abs(hist1[i]-hist2[i])/max(hist1[i],hist2[i])) else: degree = degree + 1degree = degree/len(hist1) return degree # 通过得到每个通道的直方图来计算相似度 
def classify_pHash(image1,image2): image1 = cv2.resize(image1,(32,32)) image2 = cv2.resize(image2,(32,32)) gray1 = cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY) # 将灰度图转为浮点型,再进行dct变换 dct1 = cv2.dct(np.float32(gray1)) dct2 = cv2.dct(np.float32(gray2)) # 取左上角的8*8,这些代表图片的最低频率 # 这个操作等价于c++中利用opencv实现的掩码操作 # 在python中进行掩码操作,可以直接这样取出图像矩阵的某一部分 dct1_roi = dct1[0:8,0:8] dct2_roi = dct2[0:8,0:8] hash1 = getHash(dct1_roi) hash2 = getHash(dct2_roi) return Hamming_distance(hash1,hash2) # 输入灰度图,返回hash 
def getHash(image): avreage = np.mean(image) hash = [] for i in range(image.shape[0]): for j in range(image.shape[1]): if image[i,j] > avreage: hash.append(1) else: hash.append(0) return hash# 计算汉明距离 
def Hamming_distance(hash1,hash2): num = 0for index in range(len(hash1)): if hash1[index] != hash2[index]: num += 1return num if __name__ == '__main__': img1 = cv2.imread('../Data/Hotdog/1.jpg') img2 = cv2.imread('../Data/Hotpet/1.jpg')# 取一个热狗和火锅的图做对比,效果为相似度为31,可见效果十分不好degree = classify_pHash(img1,img2) print(degree) cv2.waitKey(0)

实验结果

这里从百度图片上下载了11570张热狗的数据当作正面数据,下载了1037张火锅的图片当作负面数据。

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

实验结果用一张热狗的图和一张火锅的图做对比,可能红色和白色的底比较对应,所以相似度高了点。

这里写图片描述

这里写图片描述

第二部分:用一张照片作为正面数据的方法检测

实验步骤设计

这一部分用OpenCV先检测热狗图像的轮廓,然后和原图像透明重叠,找到相似的部分并绘制圆圈标注出来。

代码分析

ClassificationOpenCVClassifierByOneImage.py

from __future__ import division
import cv2
from matplotlib import pyplot as plt
import numpy as np
from math import cos, singreen = (0, 255, 0)
# 设置绿色# 用matplotlib制作绘图函数
def show(image):plt.figure(figsize=(10, 10))# 设置图像大小plt.imshow(image, interpolation='nearest')# 绘制展示图像def overlay_mask(mask, image):rgb_mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2RGB)img = cv2.addWeighted(rgb_mask, 0.5, image, 0.5, 0)# 叠加图像并设置图像透明度return imgdef find_biggest_contour(image):image = image.copy()image,contours, hierarchy = cv2.findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)# 设置图像的一个拷贝,并绘制图像的轮廓# cv2.findContours为图像的轮廓检测contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours]biggest_contour = max(contour_sizes, key=lambda x: x[0])[1]mask = np.zeros(image.shape, np.uint8)cv2.drawContours(mask, [biggest_contour], -1, 255, -1)# cv2.drawContours 填充轮廓的颜色return biggest_contour, maskdef circle_contour(image, contour):image_with_ellipse = image.copy()ellipse = cv2.fitEllipse(contour)cv2.ellipse(image_with_ellipse, ellipse, green, 2, cv2.LINE_AA)# 将对应的部分画圈return image_with_ellipsedef find_hotdog(image):image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)max_dimension = max(image.shape)scale = 700/max_dimensionimage = cv2.resize(image, None, fx=scale, fy=scale)image_blur = cv2.GaussianBlur(image, (7, 7), 0)image_blur_hsv = cv2.cvtColor(image_blur, cv2.COLOR_RGB2HSV)min_red = np.array([0, 100, 80])max_red = np.array([10, 256, 256])mask1 = cv2.inRange(image_blur_hsv, min_red, max_red)min_red2 = np.array([170, 100, 80])max_red2 = np.array([180, 256, 256])mask2 = cv2.inRange(image_blur_hsv, min_red2, max_red2)mask = mask1 + mask2kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15))mask_closed = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)mask_clean = cv2.morphologyEx(mask_closed, cv2.MORPH_OPEN, kernel)big_strawberry_contour, mask_strawberries = find_biggest_contour(mask_clean)overlay = overlay_mask(mask_clean, image)circled = circle_contour(overlay, big_strawberry_contour)show(circled)bgr = cv2.cvtColor(circled, cv2.COLOR_RGB2BGR)return bgrimage = cv2.imread('1.jpg')
result = find_hotdog(image)
cv2.imwrite('2.jpg', result)

实验结果

原图像:

这里写图片描述

结果图像:

这里写图片描述

第三部分:用OpenCV的Cascades方法检测

实验步骤设计

这一部分步骤比较复杂,相似的任务可以参考我的另一篇博文中的第二部分关于识别的部分。

《写真美女套图:爬虫+美女脸部识别+DCGAN脸部自动生成》

http://blog.csdn.net/sileixinhua/article/details/78816683

接下来的步骤较复杂,请仔细阅读。

  1. 在以下代码用运行GrayResizePictures()和Create_pos_n_neg()函数,用把数据集处理成灰度图数据集,然后创建正面的数据获得数据的列表在bg.txt文件中。

  2. 再当前目录下用cmd或者terminal执行opencv_createsamples两个命令,创建和整理训练集

opencv_createsamples -img watch5050.jpg -bg bg.txt -info info/info.lst -pngoutput info -maxxangle 0.5 -maxyangle 0.5 -maxzangle 0.5 -num 1106

这里是用一张原始的照片创建很多很多数据集。

原始的图片:

这里写图片描述

创建的数据集:

这里写图片描述

仔细看,负面火锅图像数据里有热狗的图片数据,这就是我们创建的数据集,这样我们有1000多张数据集了。

这里写图片描述

opencv_createsamples -info info/info.lst -num 1106 -w 20 -h 20 -vec positives.vec

这里是获取数据集的positives.vec文件,文件里是正面数据集的特征。

并创建一个data文件夹,或者命令行来创建

mkdir data

创建.xml识别器数据文件。

opencv_traincascade -data data -vec positives.vec -bg bg.txt -numPos 1000 -numNeg 500 -numStages 6 -w 20 -h 20

运行完毕之后再次运行如下命令行,虽然和上面的一样,但是还要运行一下,将data文件夹中分块的的.xml合并成一个

opencv_traincascade -data data -vec positives.vec -bg bg.txt -numPos 1000 -numNeg 500 -numStages 6 -w 20 -h 20

然后将data文件夹里生成的.xml文件名字改为cascade_hotdog.xml。

代码分析

ClassificationOpenCVClassifier.py

# -*- coding:utf-8 -*-  
# coder:橘子派_司磊
# 2017年11月5日 17点34分
# 训练你自己的类OPENCV HAAR CLASSIFIER分类器
# TRAIN YOUR OWN OPENCV HAAR CLASSIFIER
# http://coding-robin.de/2013/07/22/train-your-own-opencv-haar-classifier.html
# 热狗图片一共11582张
# 火锅照片一共1043张
# Make Your Own Haar Cascades
# https://pythonprogramming.net/haar-cascade-object-detection-python-opencv-tutorial/
# 处理后的热狗图片一共11488张
# '..\Data\HotdogResize'
# 处理后的火锅照片一共1016张
# '..\Data\HotpetResize'# 结果热狗的图片一张都没有用到
# 测试的时候记得用手机打开图片watch5050.jpg
# 笔记本运算的,所以训练集就用黑白的,样本也少,测试的时候多上下左右运动下
# 这次用的opencv3.6的cascade处理流程,的确比tensorflow之类方便点,但是要求的样本要大
# 效果没有tensorflow好,小的需求和在移动设备上可以用这种方法# 代码说明在下方主函数import cv2
import os
import numpy as npdef GrayResizePictures():if not os.path.exists('..\Data\HotdogResize'):os.makedirs('..\Data\HotdogResize')if not os.path.exists('..\Data\HotpetResize'):os.makedirs('..\Data\HotpetResize')   for HotpetRoot,HotpetDirs,HotdogFiles in os.walk('..\Data\Hotdog'):  #print(HotpetRoot)#print(HotpetDirs)#print(HotdogFiles)j = 0for i in HotdogFiles:j=j+1img = cv2.imread('..\Data\Hotdog\\'+str(HotdogFiles[j]),cv2.IMREAD_GRAYSCALE)if img is  None:continueresized_image = cv2.resize(img, (100, 100))cv2.imwrite('..\Data\HotdogResize\\'+str(HotdogFiles[j]),resized_image)for HotpetRoot,HotpetDirs,HotpetFiles in os.walk('..\Data\Hotpet'):  #print(HotpetRoot)#print(HotpetDirs)#print(HotpetFiles)j = 0for i in HotpetFiles:j=j+1img = cv2.imread('..\Data\Hotpet\\'+str(HotpetFiles[j]),cv2.IMREAD_GRAYSCALE)if img is  None:continueresized_image = cv2.resize(img, (100, 100))cv2.imwrite('..\Data\HotpetResize\\'+str(HotpetFiles[j]),resized_image)def Create_pos_n_neg():for file_type in ['HotpetResize']:for img in os.listdir(file_type):if file_type == 'pos':line = file_type+'/'+img+' 1 0 0 50 50\n'with open('info.dat','a') as f:f.write(line)elif file_type == 'HotpetResize':line = file_type+'/'+img+'\n'with open('bg.txt','a') as f:f.write(line)def Dectctive():face_cascade = cv2.CascadeClassifier('C:\\OpenCV\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_default.xml')eye_cascade = cv2.CascadeClassifier('C:\\OpenCV\\opencv\\build\\etc\\haarcascades\\haarcascade_eye.xml')watch_cascade = cv2.CascadeClassifier('C:\\Code\\HotdogOrNotHotdog\\Script\\cascade_hotdog.xml')cap = cv2.VideoCapture(0)while 1:ret, img = cap.read()gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)faces = face_cascade.detectMultiScale(gray, 1.3, 5)watches = watch_cascade.detectMultiScale(gray, 10, 10)# 这里参数可改成 5# detectMultiScale()# https://docs.opencv.org/2.4/modules/objdetect/doc/cascade_classification.html# minSize – Minimum possible object size. Objects smaller than that are ignored.# maxSize – Maximum possible object size. Objects larger than that are ignored.for (x,y,w,h) in watches:cv2.rectangle(img,(x,y),(x+w,y+h),(255,255,0),2)for (x,y,w,h) in faces:cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)roi_gray = gray[y:y+h, x:x+w]roi_color = img[y:y+h, x:x+w]eyes = eye_cascade.detectMultiScale(roi_gray)for (ex,ey,ew,eh) in eyes:cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)cv2.imshow('img',img)k = cv2.waitKey(30) & 0xffif k == 27:breakcap.release()cv2.destroyAllWindows()if __name__ == '__main__':# 1.先执行GrayResizePictures()和Create_pos_n_neg()函数# 2.再当前目录下用cmd或者terminal执行# opencv_createsamples两个命令,创建和整理训练集# 3.执行opencv_traincascade,根据训练集的数量再data文件夹下不同生成的结果# 4.然后再执行一次opencv_traincascade,记得把最后数字改成data文件夹下生成的数字# 5.执行Dectctive()函数# GrayResizePictures()# Create_pos_n_neg()# opencv_createsamples -img watch5050.jpg -bg bg.txt -info info/info.lst -pngoutput info -maxxangle 0.5 -maxyangle 0.5 -maxzangle 0.5 -num 1106# opencv_createsamples -info info/info.lst -num 1106 -w 20 -h 20 -vec positives.vec# mkdir data# opencv_traincascade -data data -vec positives.vec -bg bg.txt -numPos 1000 -numNeg 500 -numStages 6 -w 20 -h 20# opencv_traincascade -data data -vec positives.vec -bg bg.txt -numPos 1000 -numNeg 500 -numStages 5 -w 20 -h 20# 这里主要的方法就是用一张图片做正例和很多张反例图片,把整理图片缩小加入到反例图片中# 就形成了正例,然后traincascadeDectctive()

实验结果

这里写图片描述

这里大家不要误解把我的脸和眼睛也识别成热狗了,这里是三个识别器,用了不同的颜色的框展示了出来,热狗是淡蓝色的框,看来识别效果还是很好的。

——————————————————————————————————-

有学习机器学习相关同学可以加群,交流,学习,不定期更新最新的机器学习pdf书籍等资源。

QQ群号: 657119450

这里写图片描述

这篇关于三种方法检测:“热狗还是不是热狗”(OpenCV+Cascades+Hash)+ 爬虫(下载训练集)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/496621

相关文章

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

hdu1496(用hash思想统计数目)

作为一个刚学hash的孩子,感觉这道题目很不错,灵活的运用的数组的下标。 解题步骤:如果用常规方法解,那么时间复杂度为O(n^4),肯定会超时,然后参考了网上的解题方法,将等式分成两个部分,a*x1^2+b*x2^2和c*x3^2+d*x4^2, 各自作为数组的下标,如果两部分相加为0,则满足等式; 代码如下: #include<iostream>#include<algorithm

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

常用的jdk下载地址

jdk下载地址 安装方式可以看之前的博客: mac安装jdk oracle 版本:https://www.oracle.com/java/technologies/downloads/ Eclipse Temurin版本:https://adoptium.net/zh-CN/temurin/releases/ 阿里版本: github:https://github.com/

usaco 1.2 Milking Cows(类hash表)

第一种思路被卡了时间 到第二种思路的时候就觉得第一种思路太坑爹了 代码又长又臭还超时!! 第一种思路:我不知道为什么最后一组数据会被卡 超时超了0.2s左右 大概想法是 快排加一个遍历 先将开始时间按升序排好 然后开始遍历比较 1 若 下一个开始beg[i] 小于 tem_end 则说明本组数据与上组数据是在连续的一个区间 取max( ed[i],tem_end ) 2 反之 这个

浅谈主机加固,六种有效的主机加固方法

在数字化时代,数据的价值不言而喻,但随之而来的安全威胁也日益严峻。从勒索病毒到内部泄露,企业的数据安全面临着前所未有的挑战。为了应对这些挑战,一种全新的主机加固解决方案应运而生。 MCK主机加固解决方案,采用先进的安全容器中间件技术,构建起一套内核级的纵深立体防护体系。这一体系突破了传统安全防护的局限,即使在管理员权限被恶意利用的情况下,也能确保服务器的安全稳定运行。 普适主机加固措施: