├── 1_Image processing ├── Images │ ├── arc.jpg │ ├── lena.jpg │ ├── line.jpg │ ├── person.jpg │ ├── plant.jpg │ └── star.jpg ├── code │ ├── 10_canny.py │ ├── 11_edge.py │ ├── 12_corner.py │ ├── 13_add_noise.py │ ├── 14_contour_detection.py │ ├── 15_contours.py │ ├── 16_Douglas-peucker.py │ ├── 17_houghline.py │ ├── 18_HoughCircles.py │ ├── 1_image.py │ ├── 2_resize.py │ ├── 3_Change color channel.py │ ├── 4_open.py │ ├── 5_erode.py │ ├── 6_sobel.py │ ├── 7_canny.py │ ├── 8_canny.py │ └── 9_degeDetection.py └── output_images │ ├── 1.png │ ├── 10.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 7.png │ ├── 8.png │ └── 9.png ├── 2_Image segmentation ├── code │ ├── 2.1_grabcut.py │ ├── 2.2_grabcut_with-mouse.py │ └── 2.3_watershed.py ├── imges │ ├── 1.jpg │ ├── 2.jpg │ ├── ouc.jpg │ └── test.jpg └── output │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ └── 5.png ├── 3_face_detection ├── cascade │ ├── Readme │ ├── haarcascade_eye.xml │ ├── haarcascade_eye_tree_eyeglasses.xml │ ├── haarcascade_frontalcatface.xml │ ├── haarcascade_frontalcatface_extended.xml │ ├── haarcascade_frontalface_alt.xml │ ├── haarcascade_frontalface_alt2.xml │ ├── haarcascade_frontalface_alt_tree.xml │ ├── haarcascade_frontalface_default.xml │ ├── haarcascade_fullbody.xml │ ├── haarcascade_lefteye_2splits.xml │ ├── haarcascade_licence_plate_rus_16stages.xml │ ├── haarcascade_lowerbody.xml │ ├── haarcascade_profileface.xml │ ├── haarcascade_righteye_2splits.xml │ ├── haarcascade_russian_plate_number.xml │ ├── haarcascade_smile.xml │ └── haarcascade_upperbody.xml ├── code │ ├── 3.1_face_detection.py │ ├── 3.2_face_video.py │ ├── 3.3.1_face_recognition.py │ ├── 3.3.2_trainset.py │ ├── 3.3.3_recognition.py │ └── Readme ├── data │ ├── S1 │ │ ├── 1.pgm │ │ ├── 10.pgm │ │ ├── 2.pgm │ │ ├── 3.pgm │ │ ├── 4.pgm │ │ ├── 5.pgm │ │ ├── 6.pgm │ │ ├── 7.pgm │ │ ├── 8.pgm │ │ ├── 9.pgm │ │ └── Readme │ └── ren_dong │ │ └── Readme ├── images │ ├── Readme │ ├── face1.jpg │ └── face2.jpg └── output │ └── 1.png ├── 4_Feature matching ├── code │ ├── 4.1_Harris.py │ ├── 4.2_SIFT.py │ ├── 4.3_SURF.py │ ├── 4.4_fast.py │ ├── 4.5_ORB.py │ ├── 4.6_KNN.py │ ├── 4.7_FLANN.py │ ├── 4.8_danyingxing.py │ └── readme ├── images │ ├── chess.jpg │ ├── orb1.jpg │ ├── orb2.jpg │ └── readme └── readme ├── 5_face_recognition └── readme ├── 5_object_detection ├── code │ ├── 5.1_person_detect.py │ ├── 5.2_HOG.py │ ├── 5.3_BOW.py │ └── readme ├── images │ ├── person.jpg │ └── readme └── readme ├── 6_object_traack └── code │ ├── 5.4_track.py │ ├── 6.1_track.py │ ├── 6.2_KNN.py │ ├── 6.3_meanshift.py │ ├── 6.4_camshift.py │ └── readme ├── README.md ├── face_recognition ├── facial.py ├── find_face.py ├── find_face_cnn.py ├── images │ ├── 001.jpg │ ├── 002.jpg │ ├── 003.jpg │ ├── 004.jpg │ ├── 11.jpg │ ├── 22.jpg │ ├── 33.jpg │ └── readme ├── makeups.py ├── profile.py └── readme └── video2img ├── Readme ├── avi2img.py └── img2avi.py /1_Image processing/Images/arc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/Images/arc.jpg -------------------------------------------------------------------------------- /1_Image processing/Images/lena.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/Images/lena.jpg -------------------------------------------------------------------------------- /1_Image processing/Images/line.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/Images/line.jpg -------------------------------------------------------------------------------- /1_Image processing/Images/person.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/Images/person.jpg -------------------------------------------------------------------------------- /1_Image processing/Images/plant.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/Images/plant.jpg -------------------------------------------------------------------------------- /1_Image processing/Images/star.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/Images/star.jpg -------------------------------------------------------------------------------- /1_Image processing/code/10_canny.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | ''' 3 | 带有滑动条的canny边缘检测 4 | 5 | ''' 6 | import cv2 7 | import numpy as np 8 | 9 | 10 | def CannyThreshold(lowThreshold): 11 | detected_edges = cv2.GaussianBlur(gray,(3,3),0) 12 | detected_edges = cv2.Canny(detected_edges,lowThreshold,lowThreshold*ratio,apertureSize = kernel_size) 13 | dst = cv2.bitwise_and(img,img,mask = detected_edges) # just add some colours to edges from original image. 14 | cv2.imshow('canny demo',dst) 15 | 16 | lowThreshold = 0 17 | max_lowThreshold = 100 18 | ratio = 3 19 | kernel_size = 3 20 | 21 | img = cv2.imread('1.jpg') 22 | gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 23 | 24 | cv2.namedWindow('canny demo') 25 | 26 | cv2.createTrackbar('Min threshold','canny demo',lowThreshold, max_lowThreshold, CannyThreshold) 27 | 28 | CannyThreshold(0) # initialization 29 | if cv2.waitKey(0) == 27: 30 | cv2.destroyAllWindows() 31 | -------------------------------------------------------------------------------- /1_Image processing/code/11_edge.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | import cv2 3 | import numpy 4 | ''' 5 | 检测边缘 6 | 形态学检测边缘的原理很简单,在膨胀时,图像中的物体会想周围“扩张”; 7 | 腐蚀时,图像中的物体会“收缩”。比较这两幅图像,由于其变化的区域只发生在边缘。 8 | 所以这时将两幅图像相减,得到的就是图像中物体的边缘 9 | 10 | ''' 11 | 12 | image = cv2.imread("1.jpg",0) 13 | #构造一个3×3的结构元素 14 | element = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3)) 15 | dilate = cv2.dilate(image, element) 16 | erode = cv2.erode(image, element) 17 | 18 | #将两幅图像相减获得边,第一个参数是膨胀后的图像,第二个参数是腐蚀后的图像 19 | result = cv2.absdiff(dilate,erode) 20 | #上面得到的结果是灰度图,将其二值化以便更清楚的观察结果 21 | retval, result = cv2.threshold(result, 40, 255, cv2.THRESH_BINARY) 22 | #反色,即对二值图每个像素取反 23 | result = cv2.bitwise_not(result) 24 | #显示图像 25 | cv2.imshow("result",result) 26 | cv2.waitKey(0) 27 | cv2.destroyAllWindows() 28 | -------------------------------------------------------------------------------- /1_Image processing/code/12_corner.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | import cv2 3 | ''' 4 | 检测拐角 5 | 与边缘检测不同,拐角的检测的过程稍稍有些复杂。 6 | 但原理相同,所不同的是先用十字形的结构元素膨胀像素,这种情况下只会在边缘处“扩张”,角点不发生变化。 7 | 接着用菱形的结构元素腐蚀原图像,导致只有在拐角处才会“收缩”,而直线边缘都未发生变化。 8 | 9 | 第二步是用X形膨胀原图像,角点膨胀的比边要多。这样第二次用方块腐蚀时,角点恢复原状,而边要腐蚀的更多。 10 | 所以当两幅图像相减时,只保留了拐角处 11 | 12 | ''' 13 | 14 | image = cv2.imread("1.jpg", 0) 15 | origin = cv2.imread("1.jpg") 16 | #构造5×5的结构元素,分别为十字形、菱形、方形和X型 17 | cross = cv2.getStructuringElement(cv2.MORPH_CROSS,(5, 5)) 18 | #菱形结构元素的定义稍麻烦一些 19 | diamond = cv2.getStructuringElement(cv2.MORPH_RECT,(5, 5)) 20 | diamond[0, 0] = 0 21 | diamond[0, 1] = 0 22 | diamond[1, 0] = 0 23 | diamond[4, 4] = 0 24 | diamond[4, 3] = 0 25 | diamond[3, 4] = 0 26 | diamond[4, 0] = 0 27 | diamond[4, 1] = 0 28 | diamond[3, 0] = 0 29 | diamond[0, 3] = 0 30 | diamond[0, 4] = 0 31 | diamond[1, 4] = 0 32 | square = cv2.getStructuringElement(cv2.MORPH_RECT,(5, 5)) 33 | x = cv2.getStructuringElement(cv2.MORPH_CROSS,(5, 5)) 34 | #使用cross膨胀图像 35 | result1 = cv2.dilate(image,cross) 36 | #使用菱形腐蚀图像 37 | result1 = cv2.erode(result1, diamond) 38 | 39 | #使用X膨胀原图像 40 | result2 = cv2.dilate(image, x) 41 | #使用方形腐蚀图像 42 | result2 = cv2.erode(result2,square) 43 | 44 | #result = result1.copy() 45 | #将两幅闭运算的图像相减获得角 46 | result = cv2.absdiff(result2, result1) 47 | #使用阈值获得二值图 48 | retval, result = cv2.threshold(result, 40, 255, cv2.THRESH_BINARY) 49 | 50 | #在原图上用半径为5的圆圈将点标出。 51 | for j in range(result.size): 52 | y = j / result.shape[0] 53 | x = j % result.shape[0] 54 | 55 | if result[x, y] == 255: 56 | cv2.circle(image, (y, x), 5, (255,0,0)) 57 | 58 | cv2.imshow("Result", image) 59 | cv2.waitKey(0) 60 | cv2.destroyAllWindows() 61 | -------------------------------------------------------------------------------- /1_Image processing/code/13_add_noise.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from numpy import * 4 | from scipy import * 5 | import numpy as np 6 | import cv2 7 | import os 8 | 9 | '''' 10 | 对指定文件夹进行图片遍历,并添加椒盐和高斯噪声,可以进行数据增强 11 | 12 | ''' 13 | 14 | #定义添加椒盐噪声的函数 15 | def SaltAndPepper(src,percetage): 16 | SP_NoiseImg=src 17 | SP_NoiseNum=int(percetage*src.shape[0]*src.shape[1]) 18 | for i in range(SP_NoiseNum): 19 | randX=random.random_integers(0,src.shape[0]-1) 20 | randY=random.random_integers(0,src.shape[1]-1) 21 | if random.random_integers(0,1)==0: 22 | SP_NoiseImg[randX,randY]=0 23 | else: 24 | SP_NoiseImg[randX,randY]=255 25 | return SP_NoiseImg 26 | #定义添加高斯噪声的函数 27 | def addGaussianNoise(image,percetage): 28 | G_Noiseimg = image 29 | G_NoiseNum=int(percetage*image.shape[0]*image.shape[1]) 30 | for i in range(G_NoiseNum): 31 | temp_x = np.random.randint(20,40) 32 | temp_y = np.random.randint(20,40) 33 | G_Noiseimg[temp_x][temp_y] = 255 34 | return G_Noiseimg 35 | 36 | ''' 37 | 单张图片测试 38 | ''' 39 | # img = cv2.imread("1.jpg") 40 | # cv2.imshow('org',img) 41 | # salt = SaltAndPepper(img, 0.01) 42 | # cv2.imshow('salt',salt) 43 | # gauss = addGaussianNoise(img, 0.01) 44 | # cv2.imshow('gauss',gauss) 45 | # 46 | # cv2.waitKey(0) 47 | # cv2.destroyAllWindows() 48 | 49 | ''' 50 | 指定文件夹批量测试 51 | 52 | ''' 53 | class Batch(): 54 | def __init__(self): 55 | self.path = '/home/ren_dong/PycharmProjects/OpenCv/img' 56 | self.savepath = '/home/ren_dong/PycharmProjects/OpenCv/save/' 57 | 58 | def add_noise(self): 59 | filelist = os.listdir(self.path) 60 | total_num = len(filelist) 61 | i = 0 62 | n = 1 63 | while(n<=3): 64 | for item in filelist: 65 | if item.endswith('.jpg'): 66 | 67 | item = self.path + '/' + str(item) 68 | img = cv2.imread(item) 69 | cv2.imshow('org', img) 70 | percentage = 0.01 71 | percentage = percentage*(n+1) 72 | 73 | salt = SaltAndPepper(img, percentage) 74 | 75 | gauss = addGaussianNoise(salt, percentage) 76 | 77 | cv2.imshow('salt',salt) 78 | cv2.imshow('gauss',gauss) 79 | 80 | k = cv2.waitKey(0) 81 | if k == 27: 82 | cv2.destroyAllWindows() 83 | elif k == ord('s'): 84 | for count in range(1): 85 | cv2.imwrite(self.savepath + str(i) + '.jpg', salt) 86 | cv2.imwrite(self.savepath + str(i) + '0' + '.jpg', gauss) 87 | count += 1 88 | else: 89 | for count in range(1): 90 | cv2.imwrite(self.savepath + str(i) + '0' + '.jpg', gauss) 91 | count += 1 92 | 93 | i += 1 94 | 95 | n += 1 96 | 97 | 98 | 99 | if __name__ == '__main__': 100 | demo = Batch() 101 | demo.add_noise() 102 | -------------------------------------------------------------------------------- /1_Image processing/code/14_contour_detection.py: -------------------------------------------------------------------------------- 1 | #-*_ coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | ''' 5 | created on Tues jan 08:28:51 2018 6 | @author: ren_dong 7 | 8 | contour detection 9 | cv2.findContours() 寻找轮廓 10 | cv2.drawContours() 绘制轮廓 11 | 12 | 13 | ''' 14 | #加载图像img 15 | img = cv2.imread('person.jpg') 16 | cv2.imshow('origin', img) 17 | ''' 18 | 19 | 灰度化处理,注意必须调用cv2.cvtColor(), 20 | 如果直接使用cv2.imread('1.jpg',0),会提示图像深度不对,不符合cv2.CV_8U 21 | 22 | 23 | ''' 24 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 25 | cv2.imshow('gray', gray) 26 | 27 | #调用cv2.threshold()进行简单阈值化,由灰度图像得到二值化图像 28 | # 输入图像必须为单通道8位或32位浮点型 29 | ret, thresh = cv2.threshold(gray, 127, 255, 0) 30 | cv2.imshow('thresh', thresh) 31 | 32 | #调用cv2.findContours()寻找轮廓,返回修改后的图像,轮廓以及他们的层次 33 | image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 34 | cv2.imshow('image', image) 35 | 36 | 37 | print('contours[0]:',contours[0]) 38 | print('len(contours):',len(contours)) 39 | print('hierarchy.shape:',hierarchy.shape) 40 | print('hierarchy:',hierarchy) 41 | 42 | #调用cv2.drawContours()在原图上绘制轮廓 43 | img = cv2.drawContours(img, contours, -1, (0, 255, 0), 2) 44 | cv2.imshow('contours', img) 45 | 46 | 47 | 48 | cv2.waitKey() 49 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /1_Image processing/code/15_contours.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | ''' 5 | created on Tues jan 09:36:30 2018 6 | @author:ren_dong 7 | 8 | cv2.boundingRect() 边界框即直边界矩形 9 | cv2.minAreaRect() 最小矩形区域即旋转的边界矩形 10 | cv2.minEnclosingCircle() 最小闭圆 11 | 12 | ''' 13 | #载入图像img 14 | img = cv2.pyrDown(cv2.imread('star.jpg', cv2.IMREAD_UNCHANGED)) 15 | 16 | #灰度化 17 | gray = cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY) 18 | 19 | #二值化 20 | ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) 21 | 22 | #寻找轮廓 23 | image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 24 | print('hierarchy[0]:', hierarchy[0]) 25 | print('len(contours):', len(contours)) 26 | print('hierarchy.shape:', hierarchy.shape) 27 | 28 | #遍历每一个轮廓 29 | for C in contours: 30 | #计算边界框坐标 31 | x, y, w, h = cv2.boundingRect(C) 32 | 33 | ##在Img图像上绘制矩形框,颜色为green, 线宽为2 34 | cv2.rectangle(img, (x, y), (x + w, y + h), (0,255,0), 2) 35 | 36 | #计算包围目标的最小矩形区域 37 | rect = cv2.minAreaRect(C) 38 | 39 | #计算最小矩形的坐标 40 | box = cv2.boxPoints(rect) 41 | 42 | #坐标变为整数 43 | box = np.int0(box) 44 | 45 | #绘制矩形框轮廓 颜色为red 线宽为3 46 | cv2.drawContours(img, [box], 0, (0,0,255),3) 47 | 48 | #最小闭圆的圆心和半径 49 | (x,y),radius = cv2.minEnclosingCircle(C) 50 | 51 | #转换为整型 52 | center = (int(x), int(y)) 53 | radius = int(radius) 54 | 55 | #绘制最小闭圆 56 | img = cv2.circle(img,center, radius, (255, 0, 0), 2) 57 | 58 | 59 | 60 | cv2.drawContours(img,contours, -1, (0, 0, 255), 1) 61 | cv2.imshow('contours',img) 62 | 63 | 64 | cv2.waitKey() 65 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /1_Image processing/code/16_Douglas-peucker.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | ''' 5 | created on Tues jan 10:49:30 2018 6 | @author:ren_dong 7 | 8 | 凸轮廓和Douglas-Peucker算法 9 | 10 | cv2.approxPloyDP() 11 | CV2.arcLength() 12 | cv2.convexHull() 13 | 14 | ''' 15 | #读入图像img 16 | img = cv2.pyrDown(cv2.imread('arc.jpg', cv2.IMREAD_COLOR)) 17 | 18 | #resize 19 | #img = cv2.resize(img, None, fx=0.6, fy=0.6, interpolation=cv2.INTER_CUBIC) 20 | 21 | #创建空白图像,用来绘制多边形轮廓 22 | curve = np.zeros(img.shape,np.uint8) 23 | 24 | #灰度变换 25 | gray = cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY) 26 | 27 | #使用定制kernel 进行中值滤波,去除一些噪声 28 | kernel = np.ones((3,3),np.float32) / 9 29 | #这里的-1表示目标图像和原图像具有同样的深度,比如cv2.CV_8U 30 | gray = cv2.filter2D(gray,-1,kernel) 31 | 32 | #阈值化 gray image --> binary image 33 | # 输入图像必须为单通道8位或32位浮点型 34 | # 这里使用cv2.THRESH_BINARY_INV 实现效果像素>125 设置为0(黑) 否则设置为255(白) 35 | ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV) 36 | 37 | #寻找轮廓 返回修改后的图像, 图像轮廓 以及他们的层次 38 | image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 39 | 40 | 41 | ##假设contours[0]为最大轮廓 42 | cnt = contours[0] 43 | max_area = cv2.contourArea(cnt) 44 | 45 | ##遍历contours, 和原始设置比较,获得最大轮廓区域 46 | for i in contours: 47 | if cv2.contourArea(i) > max_area: 48 | cnt = i 49 | max_area = cv2.contourArea(cnt) 50 | print('max_area:',max_area) 51 | 52 | ##获得轮廓周长 53 | epsilon = 0.01 * cv2.arcLength(cnt, True) 54 | 55 | #计算得到近似的多边形框 56 | approx = cv2.approxPolyDP(cnt, epsilon, True) 57 | 58 | #得到凸包 59 | hull = cv2.convexHull(cnt) 60 | 61 | 62 | 63 | print('contours', len(contours), type(contours)) 64 | print('cnt.shape', cnt.shape, type(cnt)) 65 | print('approx.shape', approx.shape, type(approx)) 66 | print('hull.shape', hull.shape, type(hull)) 67 | 68 | 69 | 70 | #在原图像得到原始的轮廓 71 | cv2.drawContours(img, contours, -1, (255, 0 , 0),2) 72 | 73 | #在空白图像中得到最大轮廓, 多边形轮廓, 凸包轮廓 74 | cv2.drawContours(curve, [cnt], -1, (0, 0, 255), 1) # 75 | cv2.drawContours(curve, [hull], -1, (0, 255, 0), 2) ##绿色多边形轮廓 线宽2 76 | cv2.drawContours(curve, [approx], -1, (255, 0, 0), 3) ##蓝色凸包轮廓 线宽3 77 | 78 | 79 | cv2.imshow('contours',img) 80 | cv2.imshow('all',curve) 81 | 82 | 83 | cv2.waitKey() 84 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /1_Image processing/code/17_houghline.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | ''' 5 | created on Tues jan 13:57:30 2018 6 | @author:ren_dong 7 | 8 | Hough变换检测直线 9 | 10 | cv2.HoughLine() 11 | cv2.HoughLines() 12 | 13 | 14 | ''' 15 | #载入图片img 16 | img = cv2.imread('line.jpg') 17 | 18 | #灰度化 --> gray 19 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 20 | 21 | ##中值滤波去除噪声 图像平滑 22 | gray = cv2.medianBlur(gray, ksize=3) 23 | 24 | #Canny边缘检测 25 | edges = cv2.Canny(gray, 50, 120) 26 | 27 | 28 | #最小直线长度, 更短的直线会被消除 29 | minLineLength = 10 30 | 31 | #最大线段间隙,一条线段的间隙长度大于这个值会被认为是两条分开的线段 32 | maxLineGap = 5 33 | 34 | ##Hough 变换检测直线 35 | lines = cv2.HoughLinesP(edges, 1, np.pi/180, 80, minLineLength, maxLineGap) 36 | 37 | for i in range(len(lines)): 38 | for x1, y1, x2, y2 in lines[i]: 39 | #给定两点 在原始图片绘制线段 40 | cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2) 41 | 42 | 43 | cv2.imshow('edges', edges) 44 | cv2.imshow('lines', img) 45 | 46 | 47 | cv2.waitKey() 48 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /1_Image processing/code/18_HoughCircles.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | ''' 5 | created on Tues jan 14:37:10 2018 6 | @author:ren_dong 7 | 8 | Hough变换检测圆 9 | 10 | cv2.HoughCricles() 11 | 12 | 13 | ''' 14 | #载入图片img 15 | img = cv2.imread('plant.jpg') 16 | 17 | #灰度化处理 --> gray image 18 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 19 | 20 | ##中值滤波 图像平滑 21 | gray = cv2.medianBlur(gray, 7) 22 | 23 | ##Hough变换检测圆 24 | circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 200, 25 | param1=200, param2=20, minRadius= 0, maxRadius=0 ) 26 | 27 | circles = np.uint16(np.around(circles)) 28 | 29 | 30 | ##绘制圆 31 | for i in circles[0,:]: 32 | cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 2) 33 | cv2.circle(img, (i[0], i[1]), 2, (0, 0, 255), 2) 34 | 35 | 36 | cv2.imshow('HoughCircles',img) 37 | 38 | 39 | cv2.waitKey() 40 | cv2.destroyAllWindows() 41 | -------------------------------------------------------------------------------- /1_Image processing/code/1_image.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import numpy as np 3 | import cv2 4 | from matplotlib import pyplot as plt 5 | 6 | ##使用matplotlib显示图像 7 | 8 | ##彩色图像使用OpenCV加载时是BGR模式,但是matplotlib是RGB模式。 9 | ''' 10 | img = cv2.imread('000028.jpg', 0) 11 | plt.imshow(img, cmap = 'gray', interpolation= 'bicubic') 12 | plt.xticks([]),plt.yticks([]) 13 | plt.show() 14 | 15 | ''' 16 | 17 | #使用opencv显示图像并保存 18 | 19 | 20 | img = cv2.imread('000028.jpg', 3) 21 | cv2.namedWindow('image', cv2.WINDOW_NORMAL) ##创建一个窗口,调整窗口大小 22 | cv2.imshow('image', img) 23 | k = cv2.waitKey(0) 24 | if k == ord('q'): #wait for q key to exit 25 | cv2.destroyAllWindows() 26 | elif k == ord('s'): #wait for 's' to save and exit 27 | cv2.imwrite('1.jpg', img) 28 | img1 = cv2.imread('1.jpg', 0) 29 | cv2.imshow('gray', img1) 30 | cv2.waitKey(0) 31 | cv2.destroyAllWindows() 32 | 33 | -------------------------------------------------------------------------------- /1_Image processing/code/2_resize.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | 5 | ''' 6 | 几何变换 7 | 8 | ''' 9 | # #resize 10 | # img = cv2.imread('1.jpg') 11 | # 12 | # ##不指定具体尺寸, 按照比例进行resize 13 | # # res = cv2.resize(img,None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR) 14 | # 15 | # ###直接给定缩放尺寸 16 | # res = cv2.resize(img, (640,480),interpolation=cv2.INTER_LINEAR) 17 | # 18 | # while(1): 19 | # cv2.imshow('img',img) 20 | # cv2.imshow('res',res) 21 | # 22 | # k = cv2.waitKey(1) & 0xff 23 | # if k == 27 : 24 | # break 25 | # 26 | # cv2.destroyWindow() 27 | 28 | ##rotation 29 | 30 | img = cv2.imread('1.jpg') 31 | 32 | rows, cols, ch = img.shape 33 | 34 | ###给定旋转矩阵 2*3 35 | M = cv2.getRotationMatrix2D((rows/2,cols/2), 30, 0.8) 36 | 37 | dst = cv2.warpAffine(img, M, (2*rows,2*cols)) 38 | 39 | cv2.imshow('img',img) 40 | cv2.imshow('res',dst) 41 | cv2.waitKey(0) 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /1_Image processing/code/3_Change color channel.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | 5 | ''' 6 | 使用numpy索引制定图片通道,改变相应像素值,CV加载彩色图像为BGR 7 | 8 | ''' 9 | 10 | img = cv2.imread('1.jpg') 11 | print img.shape 12 | print img.size 13 | print img.dtype 14 | img[:,:,2] = 0 ###0,1,2 = B, R, G 15 | cv2.imshow('img',img) 16 | k = cv2.waitKey(0) 17 | if k == 27: 18 | cv2.destroyAllWindows() 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /1_Image processing/code/4_open.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import cv2 3 | import numpy as np 4 | ''' 5 | 6 | 开运算和闭运算就是将腐蚀和膨胀按照一定的次序进行处理。但这两者并不是可逆的,即先开后闭并不能得到原先的图像 7 | 闭运算用来连接被误分为许多小块的对象,而开运算用于移除由图像噪音形成的斑点 8 | 因此,某些情况下可以连续运用这两种运算。如对一副二值图连续使用闭运算和开运算,将获得图像中的主要对象。 9 | 同样,如果想消除图像中的噪声(即图像中的“小点”),也可以对图像先用开运算后用闭运算,不过这样也会消除一些破碎的对象。 10 | 11 | 12 | ''' 13 | img = cv2.imread('1.jpg', 0) 14 | # 定义结构元素 15 | kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) 16 | 17 | # 闭运算 18 | closed = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) 19 | # 显示腐蚀后的图像 20 | cv2.imshow("Close", closed) 21 | 22 | # 开运算 23 | opened = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) 24 | # 显示腐蚀后的图像 25 | cv2.imshow("Open", opened) 26 | 27 | cv2.waitKey(0) 28 | cv2.destroyAllWindows() 29 | -------------------------------------------------------------------------------- /1_Image processing/code/5_erode.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | import cv2 3 | import numpy as np 4 | 5 | ''' 6 | 腐蚀和膨胀 7 | 腐蚀和膨胀的处理很简单,只需设置好结构元素,然后分别调用cv2.erode(...)和cv2.dilate(...)函数即可, 8 | 其中第一个参数是需要处理的图像,第二个是结构元素。返回处理好的图像。 9 | ''' 10 | img = cv2.imread('1.jpg', 0) 11 | # OpenCV定义的结构元素 12 | kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) 13 | # 腐蚀图像 14 | eroded = cv2.erode(img, kernel) 15 | # 显示腐蚀后的图像 16 | cv2.imshow("Eroded Image", eroded) 17 | 18 | # 膨胀图像 19 | dilated = cv2.dilate(img, kernel) 20 | # 显示膨胀后的图像 21 | cv2.imshow("Dilated Image", dilated) 22 | # 原图像 23 | cv2.imshow("Origin", img) 24 | 25 | # NumPy定义的结构元素 26 | NpKernel = np.uint8(np.ones((3, 3))) 27 | Nperoded = cv2.erode(img, NpKernel) 28 | # 显示腐蚀后的图像 29 | cv2.imshow("Eroded by NumPy kernel", Nperoded) 30 | 31 | cv2.waitKey(0) 32 | cv2.destroyAllWindows() 33 | -------------------------------------------------------------------------------- /1_Image processing/code/6_sobel.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | ''' 3 | sobel算子 uint8 8维无符号数 4 | cv2.cv_16s 16维有符号数 5 | 6 | ''' 7 | 8 | import cv2 9 | 10 | img = cv2.imread('1.jpg', 0) 11 | 12 | x = cv2.Sobel(img,cv2.CV_16S,1,0) #对x方向进行求导1,0 13 | y = cv2.Sobel(img,cv2.CV_16S,0,1) #对y方向进行求导0,1,选用cv_16s 避免图像显示不全 14 | 15 | absX = cv2.convertScaleAbs(x) ##对x,和y方向进行还原uint8,用来显示图片 16 | absY = cv2.convertScaleAbs(y) 17 | 18 | dst = cv2.addWeighted(absX,0.5,absY,0.5,0) 19 | 20 | cv2.imshow("absX", absX) 21 | cv2.imshow("absY", absY) 22 | 23 | cv2.imshow("Result", dst) 24 | 25 | cv2.waitKey(0) 26 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /1_Image processing/code/7_canny.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | ''' 5 | Canny边缘检测 6 | 1 使用高斯滤波器进行去除图像噪声 7 | 2 计算图像梯度 8 | 3 非极大值抑制 9 | 4 滞后阈值即在检测边缘上使用双阈值去除假阳性 10 | 5 分析所有边缘与其之间的连接,以保留真正的边缘消除不明显的边缘 11 | 12 | ''' 13 | img = cv2.imread('1.jpg') 14 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 15 | img = cv2.GaussianBlur(gray, (3,3), 0) 16 | canny = cv2.Canny(img,20,100) 17 | 18 | cv2.imshow('canny',canny) 19 | cv2.waitKey(0) 20 | cv2.destroyAllWindows() 21 | 22 | -------------------------------------------------------------------------------- /1_Image processing/code/8_canny.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | ''' 3 | 带有滑动条的canny边缘检测 4 | 5 | ''' 6 | import cv2 7 | import numpy as np 8 | 9 | 10 | def CannyThreshold(lowThreshold): 11 | detected_edges = cv2.GaussianBlur(gray,(3,3),0) 12 | detected_edges = cv2.Canny(detected_edges,lowThreshold,lowThreshold*ratio,apertureSize = kernel_size) 13 | dst = cv2.bitwise_and(img,img,mask = detected_edges) # just add some colours to edges from original image. 14 | cv2.imshow('canny demo',dst) 15 | 16 | lowThreshold = 0 17 | max_lowThreshold = 100 18 | ratio = 3 19 | kernel_size = 3 20 | 21 | img = cv2.imread('1.jpg') 22 | gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) 23 | 24 | cv2.namedWindow('canny demo') 25 | 26 | cv2.createTrackbar('Min threshold','canny demo',lowThreshold, max_lowThreshold, CannyThreshold) 27 | 28 | CannyThreshold(0) # initialization 29 | if cv2.waitKey(0) == 27: 30 | cv2.destroyAllWindows() 31 | -------------------------------------------------------------------------------- /1_Image processing/code/9_degeDetection.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | import numpy as np 3 | import cv2 4 | 5 | ''' 6 | 自定义函数进行边缘检测 7 | 1 使用medianBlur()作为模糊函数,去除彩色图像的噪声 8 | 2 灰度化 9 | 3 使用Laplacian()作为边缘检测函数,产生边缘线条 10 | 4 归一化 并进行边缘和背景的黑白转换(之前是背景黑,边缘白,乘以原图像将边缘变黑) 11 | 12 | ''' 13 | 14 | def strokeEdge(src, blurKsize = 7, edgeKsize = 5): 15 | ''' 16 | 17 | :param src: 原图像 BGR彩色空间 18 | :param blurKsize: 模糊滤波器kernel size k<3 不进行模糊操作 19 | :param edgeKsize: 边缘检测kernel size 20 | :return: dst 21 | 22 | 23 | ''' 24 | if blurKsize >= 3: 25 | ##中值模糊 26 | blurredSrc = cv2.medianBlur(src, blurKsize) 27 | #灰度化 28 | gray = cv2.cvtColor(blurredSrc, cv2.COLOR_BGR2GRAY) 29 | else: 30 | #灰度化 31 | gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) 32 | 33 | cv2.imshow('gray',gray) 34 | ###边缘检测 35 | laplacian = cv2.Laplacian(gray, cv2.CV_8U, gray, ksize= edgeKsize) 36 | cv2.imshow('Laplacian',laplacian) 37 | ##归一化 转换背景 38 | normalizeInverse = (1.0/255)*(255- gray) 39 | cv2.imshow('normalizeInverse', normalizeInverse) 40 | ##分离通道 41 | channels = cv2.split(src) 42 | 43 | ##计算后的结果与每个通道相乘 44 | for channel in channels: 45 | ##这里是点乘 即对应原素相乘 46 | channel[:] = channel * normalizeInverse 47 | 48 | cv2.imshow('B',channels[0]) 49 | #合并通道 50 | return cv2.merge(channels) 51 | 52 | 53 | img = cv2.imread('1.jpg',cv2.IMREAD_COLOR) 54 | dst = strokeEdge(img) 55 | cv2.imshow('dst',dst) 56 | cv2.waitKey() 57 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /1_Image processing/output_images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/output_images/1.png -------------------------------------------------------------------------------- /1_Image processing/output_images/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/output_images/10.png -------------------------------------------------------------------------------- /1_Image processing/output_images/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/output_images/2.png -------------------------------------------------------------------------------- /1_Image processing/output_images/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/output_images/3.png -------------------------------------------------------------------------------- /1_Image processing/output_images/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/output_images/4.png -------------------------------------------------------------------------------- /1_Image processing/output_images/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/output_images/5.png -------------------------------------------------------------------------------- /1_Image processing/output_images/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/output_images/6.png -------------------------------------------------------------------------------- /1_Image processing/output_images/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/output_images/7.png -------------------------------------------------------------------------------- /1_Image processing/output_images/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/output_images/8.png -------------------------------------------------------------------------------- /1_Image processing/output_images/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/1_Image processing/output_images/9.png -------------------------------------------------------------------------------- /2_Image segmentation/code/2.1_grabcut.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | 5 | ''' 6 | created on 08:10:27 2018-11-15 7 | @author:ren_dong 8 | 9 | Grabcut 图像分割 10 | 11 | 直接给定矩形区域作为ROI 12 | 13 | GrabCut算法的实现步骤: 14 | 15 | 1 在图片中定义(一个或者多个)包含物体的矩形。 16 | 2 矩形外的区域被自动认为是背景。 17 | 3 对于用户定义的矩形区域,可用背景中的数据来区分它里面的前景和背景区域。 18 | 4 用高斯混合模型(GMM)来对背景和前景建模,并将未定义的像素标记为可能的前景或者背景。 19 | 5 图像中的每一个像素都被看做通过虚拟边与周围像素相连接,而每条边都有一个属于前景或者背景的概率,这是基于它与周边像素颜色上的相似性。 20 | 6 每一个像素(即算法中的节点)会与一个前景或背景节点连接。 21 | 7 在节点完成连接后(可能与背景或前景连接),若节点之间的边属于不同终端(即一个节点属于前景,另一个节点属于背景),则会切断他们之间的边,这就能将图像各部分分割出来。 22 | 23 | 24 | cv2.grabCut(img, mask, rect, bgdModel, fgdModel, iterCount[, mode]) → None 25 | 26 | 27 | ''' 28 | #载入图像img 29 | fname = 'test.jpg' 30 | img = cv2.imread(fname) 31 | 32 | #设定矩形区域 作为ROI 矩形区域外作为背景 33 | rect = (275, 120, 170, 320) 34 | 35 | #img.shape[:2]得到img的row 和 col , 36 | # 得到和img尺寸一样的掩模即mask ,然后用0填充 37 | mask = np.zeros(img.shape[:2], np.uint8) 38 | 39 | #创建以0填充的前景和背景模型, 输入必须是单通道的浮点型图像, 1行, 13x5 = 65的列 即(1,65) 40 | bgModel = np.zeros((1,65), np.float64) 41 | fgModel = np.zeros((1,65), np.float64) 42 | 43 | #调用grabcut函数进行分割,输入图像img, mask, mode为 cv2.GC_INIT_WITH-RECT 44 | cv2.grabCut(img, mask, rect, bgModel, fgModel, 5, cv2.GC_INIT_WITH_RECT) 45 | 46 | ##调用grabcut得到rect[0,1,2,3],将0,2合并为0, 1,3合并为1 存放于mask2中 47 | mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype(np.uint8) 48 | 49 | #得到输出图像 50 | out = img * mask2[:, :, np.newaxis] 51 | 52 | cv2.imshow('origin', img) 53 | cv2.imshow('grabcut', out) 54 | cv2.waitKey() 55 | cv2.destroyAllWindows() 56 | 57 | -------------------------------------------------------------------------------- /2_Image segmentation/code/2.2_grabcut_with-mouse.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | 5 | ''' 6 | created on 08:10:27 2018-11-15 7 | @author:ren_dong 8 | 9 | Grabcut 图像分割 10 | 11 | 加入鼠标回调函数,可以进行交互式操作,鼠标选择矩形区域作为ROI 12 | 13 | cv2.grabCut(img, mask, rect, bgdModel, fgdModel, iterCount[, mode]) → None 14 | on_mouse() 15 | 16 | 17 | ''' 18 | 19 | # 鼠标事件的回调函数 20 | def on_mouse(event, x, y, flag, param): 21 | global rect 22 | global leftButtonDown 23 | global leftButtonUp 24 | 25 | # 鼠标左键按下 26 | if event == cv2.EVENT_LBUTTONDOWN: 27 | rect[0] = x 28 | rect[2] = x 29 | rect[1] = y 30 | rect[3] = y 31 | leftButtonDown = True 32 | leftButtonUp = False 33 | 34 | # 移动鼠标事件 35 | if event == cv2.EVENT_MOUSEMOVE: 36 | if leftButtonDown and not leftButtonUp: 37 | rect[2] = x 38 | rect[3] = y 39 | 40 | # 鼠标左键松开 41 | if event == cv2.EVENT_LBUTTONUP: 42 | if leftButtonDown and not leftButtonUp: 43 | x_min = min(rect[0], rect[2]) 44 | y_min = min(rect[1], rect[3]) 45 | 46 | x_max = max(rect[0], rect[2]) 47 | y_max = max(rect[1], rect[3]) 48 | 49 | rect[0] = x_min 50 | rect[1] = y_min 51 | rect[2] = x_max 52 | rect[3] = y_max 53 | leftButtonDown = False 54 | leftButtonUp = True 55 | 56 | 57 | # 读入图片 58 | img = cv2.imread('ouc.jpg') 59 | ''' 60 | 61 | 掩码图像,如果使用掩码进行初始化,那么mask保存初始化掩码信息; 62 | 在执行分割的时候,也可以将用户交互所设定的前景与背景保存到mask中, 63 | 然后再传入grabCut函数; 64 | 在处理结束之后,mask中会保存结果 65 | 66 | ''' 67 | #img.shape[:2]=img.shape[0:2] 代表取彩色图像的长和宽 img.shape[:3] 代表取长+宽+通道 68 | mask = np.zeros(img.shape[:2], np.uint8) 69 | 70 | # 背景模型,如果为None,函数内部会自动创建一个bgdModel;bgdModel必须是单通道浮点型图像,且行数只能为1,列数只能为13x5; 71 | bgdModel = np.zeros((1, 65), np.float64) 72 | # fgdModel——前景模型,如果为None,函数内部会自动创建一个fgdModel;fgdModel必须是单通道浮点型图像,且行数只能为1,列数只能为13x5; 73 | fgdModel = np.zeros((1, 65), np.float64) 74 | 75 | # 用于限定需要进行分割的图像范围,只有该矩形窗口内的图像部分才被处理; 76 | # rect 初始化 77 | rect = [0, 0, 0, 0] 78 | 79 | # 鼠标左键按下 80 | leftButtonDown = False 81 | # 鼠标左键松开 82 | leftButtonUp = True 83 | 84 | # 指定窗口名来创建窗口 85 | cv2.namedWindow('img') 86 | # 设置鼠标事件回调函数 来获取鼠标输入 87 | cv2.setMouseCallback('img', on_mouse) 88 | 89 | # 显示图片 90 | cv2.imshow('img', img) 91 | 92 | 93 | ##设定循环,进行交互式操作 94 | while cv2.waitKey(2) == -1: 95 | # 左键按下,画矩阵 96 | if leftButtonDown and not leftButtonUp: 97 | 98 | img_copy = img.copy() 99 | # 在img图像上,绘制矩形 线条颜色为green 线宽为2 100 | cv2.rectangle(img_copy, (rect[0], rect[1]), (rect[2], rect[3]), (0, 255, 0), 2) 101 | # 显示图片 102 | cv2.imshow('img', img_copy) 103 | 104 | # 左键松开,矩形画好 105 | elif not leftButtonDown and leftButtonUp and rect[2] - rect[0] != 0 and rect[3] - rect[1] != 0: 106 | # 转换为宽度高度 107 | rect[2] = rect[2] - rect[0] 108 | rect[3] = rect[3] - rect[1] 109 | # rect_copy = tuple(rect.copy()) 110 | rect_copy = tuple(rect) 111 | rect = [0, 0, 0, 0] 112 | # 物体分割 113 | cv2.grabCut(img, mask, rect_copy, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT) 114 | 115 | mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8') 116 | img_show = img * mask2[:, :, np.newaxis] 117 | # 显示图片分割后结果 118 | cv2.imshow('grabcut', img_show) 119 | # 显示原图 120 | cv2.imshow('img', img) 121 | 122 | cv2.waitKey() 123 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /2_Image segmentation/code/2.3_watershed.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | 5 | ''' 6 | created on 11:10:10 2018-11-15 7 | @author:ren_dong 8 | 9 | 分水岭算法 图像分割 10 | 11 | 分水岭算法实现图像自动分割的步骤: 12 | 13 | 1 图像灰度化、Canny边缘检测 14 | 2 查找轮廓,并且把轮廓信息按照不同的编号绘制到watershed的第二个参数markers上,相当于标记注水点。 15 | 3 watershed分水岭算法 16 | 4 绘制分割出来的区域,然后使用随机颜色填充,再跟源图像融合,以得到更好的显示效果。 17 | 18 | 19 | cv2.watershed(image, markers) → None 20 | 21 | 22 | ''' 23 | 24 | 25 | # 读入图片 26 | img = cv2.imread('1.jpg') 27 | cv2.imshow('origin',img) 28 | 29 | # 转换为灰度图片 30 | gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 31 | 32 | # canny边缘检测 函数返回一副二值图,其中包含检测出的边缘。 33 | canny = cv2.Canny(gray_img, 80, 150) 34 | cv2.imshow('Canny', canny) 35 | 36 | # 寻找图像轮廓 返回修改后的图像 图像的轮廓 以及它们的层次 37 | canny, contours, hierarchy = cv2.findContours(canny, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 38 | 39 | # 32位有符号整数类型 40 | marks = np.zeros(img.shape[:2], np.int32) 41 | 42 | # findContours检测到的轮廓 43 | imageContours = np.zeros(img.shape[:2], np.uint8) 44 | 45 | # 轮廓颜色 46 | compCount = 0 47 | index = 0 48 | # 绘制每一个轮廓 49 | 50 | 51 | for index in range(len(contours)): 52 | 53 | # 对marks进行标记,对不同区域的轮廓使用不同的亮度绘制,相当于设置注水点,有多少个轮廓,就有多少个注水点 54 | # 图像上不同线条的灰度值是不同的,底部略暗,越往上灰度越高 55 | marks = cv2.drawContours(marks, contours, index, (index, index, index), 1, 8, hierarchy) 56 | 57 | # 绘制轮廓,亮度一样 58 | # masks底部亮度暗,越往上亮度越高, imageContours 整体亮度一致 59 | # imageContours = cv2.drawContours(imageContours, contours, index, (255, 255, 255), 1, 8, hierarchy) 60 | 61 | 62 | # 查看 使用线性变换转换输入数组元素成8位无符号整型。 63 | markerShows = cv2.convertScaleAbs(marks) 64 | cv2.imshow('markerShows', markerShows) 65 | # cv2.imshow('imageContours',imageContours) 66 | 67 | 68 | # 使用分水岭算法 69 | marks = cv2.watershed(img, marks) 70 | afterWatershed = cv2.convertScaleAbs(marks) 71 | 72 | cv2.imshow('afterWatershed', afterWatershed) 73 | 74 | ###分水岭算法之后,让水漫起来,并且把堤坝即分水岭绘制为绿色 75 | img[marks == -1] = [ 0, 255, 0] 76 | cv2.imshow('masks',img) 77 | 78 | ###到此 分水岭算法已经算是完成,下面是利用numpy生成随机颜色,进行填充空白图像,然后将其和原图像融合 79 | 80 | 81 | 82 | 83 | # 生成随机颜色 84 | colorTab = np.zeros((np.max(marks) + 1, 3)) 85 | # 生成0~255之间的随机数 86 | for i in range(len(colorTab)): 87 | aa = np.random.uniform(0, 255) 88 | bb = np.random.uniform(0, 255) 89 | cc = np.random.uniform(0, 255) 90 | colorTab[i] = np.array([aa, bb, cc], np.uint8) 91 | 92 | bgrImage = np.zeros(img.shape, np.uint8) 93 | 94 | # 遍历marks每一个元素值,对每一个区域进行颜色填充 95 | for i in range(marks.shape[0]): 96 | for j in range(marks.shape[1]): 97 | # index值一样的像素表示在一个区域 98 | index = marks[i][j] 99 | # 判断是不是区域与区域之间的分界,如果是边界(-1),则使用白色显示 100 | if index == -1: 101 | bgrImage[i][j] = np.array([255, 255, 255]) 102 | else: 103 | bgrImage[i][j] = colorTab[index] 104 | cv2.imshow('After ColorFill', bgrImage) 105 | 106 | # 填充后与原始图像融合 107 | result = cv2.addWeighted(img, 0.55, bgrImage, 0.45, 0) 108 | cv2.imshow('addWeighted', result) 109 | 110 | cv2.waitKey() 111 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /2_Image segmentation/imges/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/2_Image segmentation/imges/1.jpg -------------------------------------------------------------------------------- /2_Image segmentation/imges/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/2_Image segmentation/imges/2.jpg -------------------------------------------------------------------------------- /2_Image segmentation/imges/ouc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/2_Image segmentation/imges/ouc.jpg -------------------------------------------------------------------------------- /2_Image segmentation/imges/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/2_Image segmentation/imges/test.jpg -------------------------------------------------------------------------------- /2_Image segmentation/output/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/2_Image segmentation/output/1.png -------------------------------------------------------------------------------- /2_Image segmentation/output/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/2_Image segmentation/output/2.png -------------------------------------------------------------------------------- /2_Image segmentation/output/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/2_Image segmentation/output/3.png -------------------------------------------------------------------------------- /2_Image segmentation/output/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/2_Image segmentation/output/4.png -------------------------------------------------------------------------------- /2_Image segmentation/output/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/2_Image segmentation/output/5.png -------------------------------------------------------------------------------- /3_face_detection/cascade/Readme: -------------------------------------------------------------------------------- 1 | The cascade stores the Haar cascading file, 2 | 3 | that is, the xml file that holds the relevant feature matrix. 4 | -------------------------------------------------------------------------------- /3_face_detection/cascade/haarcascade_licence_plate_rus_16stages.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 64 16 7 | 8 | <_> 9 | 10 | 11 | <_> 12 | 13 | <_> 14 | 15 | 16 | 17 | <_> 18 | 32 2 8 6 -1. 19 | <_> 20 | 32 4 8 2 3. 21 | 0 22 | 1.6915600746870041e-002 23 | -9.5547717809677124e-001 24 | 8.9129137992858887e-001 25 | <_> 26 | 27 | <_> 28 | 29 | 30 | 31 | <_> 32 | 0 4 6 10 -1. 33 | <_> 34 | 3 4 3 10 2. 35 | 0 36 | 2.4228349328041077e-002 37 | -9.2089319229125977e-001 38 | 8.8723921775817871e-001 39 | <_> 40 | 41 | <_> 42 | 43 | 44 | 45 | <_> 46 | 55 0 8 6 -1. 47 | <_> 48 | 55 0 4 3 2. 49 | <_> 50 | 59 3 4 3 2. 51 | 0 52 | -1.0168660432100296e-002 53 | 8.8940089941024780e-001 54 | -7.7847331762313843e-001 55 | <_> 56 | 57 | <_> 58 | 59 | 60 | 61 | <_> 62 | 44 7 4 9 -1. 63 | <_> 64 | 44 10 4 3 3. 65 | 0 66 | 2.0863260142505169e-003 67 | -8.7998157739639282e-001 68 | 5.8651781082153320e-001 69 | -2.0683259963989258e+000 70 | -1 71 | -1 72 | <_> 73 | 74 | 75 | <_> 76 | 77 | <_> 78 | 79 | 80 | 81 | <_> 82 | 29 1 16 4 -1. 83 | <_> 84 | 29 3 16 2 2. 85 | 0 86 | 2.9062159359455109e-002 87 | -8.7765061855316162e-001 88 | 8.5373121500015259e-001 89 | <_> 90 | 91 | <_> 92 | 93 | 94 | 95 | <_> 96 | 0 5 9 8 -1. 97 | <_> 98 | 3 5 3 8 3. 99 | 0 100 | 2.3903399705886841e-002 101 | -9.2079448699951172e-001 102 | 7.5155001878738403e-001 103 | <_> 104 | 105 | <_> 106 | 107 | 108 | 109 | <_> 110 | 44 0 20 14 -1. 111 | <_> 112 | 44 0 10 7 2. 113 | <_> 114 | 54 7 10 7 2. 115 | 0 116 | -3.5404648631811142e-002 117 | 6.7834627628326416e-001 118 | -9.0937072038650513e-001 119 | <_> 120 | 121 | <_> 122 | 123 | 124 | 125 | <_> 126 | 41 7 6 9 -1. 127 | <_> 128 | 43 7 2 9 3. 129 | 0 130 | 6.2988721765577793e-003 131 | -8.1054258346557617e-001 132 | 5.8985030651092529e-001 133 | <_> 134 | 135 | <_> 136 | 137 | 138 | 139 | <_> 140 | 0 4 21 4 -1. 141 | <_> 142 | 7 4 7 4 3. 143 | 0 144 | 3.4959490876644850e-003 145 | -9.7632282972335815e-001 146 | 4.5473039150238037e-001 147 | -1.6632349491119385e+000 148 | 0 149 | -1 150 | <_> 151 | 152 | 153 | <_> 154 | 155 | <_> 156 | 157 | 158 | 159 | <_> 160 | 31 2 11 6 -1. 161 | <_> 162 | 31 4 11 2 3. 163 | 0 164 | 2.3864099755883217e-002 165 | -9.3137168884277344e-001 166 | 8.2478952407836914e-001 167 | <_> 168 | 169 | <_> 170 | 171 | 172 | 173 | <_> 174 | 56 3 6 11 -1. 175 | <_> 176 | 59 3 3 11 2. 177 | 0 178 | -2.5775209069252014e-002 179 | 8.5526448488235474e-001 180 | -8.7574672698974609e-001 181 | <_> 182 | 183 | <_> 184 | 185 | 186 | 187 | <_> 188 | 32 14 32 2 -1. 189 | <_> 190 | 32 15 32 1 2. 191 | 0 192 | -1.0646049864590168e-002 193 | 8.5167151689529419e-001 194 | -6.7789041996002197e-001 195 | <_> 196 | 197 | <_> 198 | 199 | 200 | 201 | <_> 202 | 0 2 8 14 -1. 203 | <_> 204 | 4 2 4 14 2. 205 | 0 206 | 2.7000989764928818e-002 207 | -8.0041092634201050e-001 208 | 6.4893317222595215e-001 209 | <_> 210 | 211 | <_> 212 | 213 | 214 | 215 | <_> 216 | 19 0 22 6 -1. 217 | <_> 218 | 19 0 11 3 2. 219 | <_> 220 | 30 3 11 3 2. 221 | 0 222 | 5.2989721298217773e-003 223 | -9.5342522859573364e-001 224 | 5.0140267610549927e-001 225 | -1.3346730470657349e+000 226 | 1 227 | -1 228 | <_> 229 | 230 | 231 | <_> 232 | 233 | <_> 234 | 235 | 236 | 237 | <_> 238 | 56 0 6 6 -1. 239 | <_> 240 | 56 0 3 3 2. 241 | <_> 242 | 59 3 3 3 2. 243 | 0 244 | -6.9233630783855915e-003 245 | 8.2654470205307007e-001 246 | -8.5396027565002441e-001 247 | <_> 248 | 249 | <_> 250 | 251 | 252 | 253 | <_> 254 | 32 0 14 12 -1. 255 | <_> 256 | 32 0 7 6 2. 257 | <_> 258 | 39 6 7 6 2. 259 | 0 260 | 1.2539249658584595e-001 261 | -1.2996139936149120e-002 262 | -3.2377028808593750e+003 263 | <_> 264 | 265 | <_> 266 | 267 | 268 | 269 | <_> 270 | 2 1 43 4 -1. 271 | <_> 272 | 2 3 43 2 2. 273 | 0 274 | 6.3474893569946289e-002 275 | -6.4648061990737915e-001 276 | 8.2302427291870117e-001 277 | <_> 278 | 279 | <_> 280 | 281 | 282 | 283 | <_> 284 | 34 10 30 5 -1. 285 | <_> 286 | 44 10 10 5 3. 287 | 0 288 | 4.2217150330543518e-002 289 | -7.5190877914428711e-001 290 | 6.3705182075500488e-001 291 | <_> 292 | 293 | <_> 294 | 295 | 296 | 297 | <_> 298 | 0 9 9 5 -1. 299 | <_> 300 | 3 9 3 5 3. 301 | 0 302 | 2.0000640302896500e-002 303 | -6.2077498435974121e-001 304 | 6.1317932605743408e-001 305 | -1.6521669626235962e+000 306 | 2 307 | -1 308 | <_> 309 | 310 | 311 | <_> 312 | 313 | <_> 314 | 315 | 316 | 317 | <_> 318 | 2 1 43 6 -1. 319 | <_> 320 | 2 3 43 2 3. 321 | 0 322 | 9.2297486960887909e-002 323 | -7.2764229774475098e-001 324 | 8.0554759502410889e-001 325 | <_> 326 | 327 | <_> 328 | 329 | 330 | 331 | <_> 332 | 53 4 9 8 -1. 333 | <_> 334 | 56 4 3 8 3. 335 | 0 336 | 2.7613969519734383e-002 337 | -7.0769268274307251e-001 338 | 7.3315787315368652e-001 339 | <_> 340 | 341 | <_> 342 | 343 | 344 | 345 | <_> 346 | 36 4 14 8 -1. 347 | <_> 348 | 36 4 7 4 2. 349 | <_> 350 | 43 8 7 4 2. 351 | 0 352 | 1.2465449981391430e-002 353 | -8.4359270334243774e-001 354 | 5.7046437263488770e-001 355 | <_> 356 | 357 | <_> 358 | 359 | 360 | 361 | <_> 362 | 14 14 49 2 -1. 363 | <_> 364 | 14 15 49 1 2. 365 | 0 366 | -2.3886829614639282e-002 367 | 8.2656508684158325e-001 368 | -5.2783298492431641e-001 369 | -1.4523630142211914e+000 370 | 3 371 | -1 372 | <_> 373 | 374 | 375 | <_> 376 | 377 | <_> 378 | 379 | 380 | 381 | <_> 382 | 0 5 4 9 -1. 383 | <_> 384 | 2 5 2 9 2. 385 | 0 386 | 1.8821349367499352e-002 387 | -8.1122857332229614e-001 388 | 6.9127470254898071e-001 389 | <_> 390 | 391 | <_> 392 | 393 | 394 | 395 | <_> 396 | 21 1 38 4 -1. 397 | <_> 398 | 21 3 38 2 2. 399 | 0 400 | 6.1703320592641830e-002 401 | -7.6482647657394409e-001 402 | 6.4212161302566528e-001 403 | <_> 404 | 405 | <_> 406 | 407 | 408 | 409 | <_> 410 | 44 12 18 3 -1. 411 | <_> 412 | 53 12 9 3 2. 413 | 0 414 | -1.6298670321702957e-002 415 | 5.0207728147506714e-001 416 | -8.4020161628723145e-001 417 | <_> 418 | 419 | <_> 420 | 421 | 422 | 423 | <_> 424 | 10 4 9 3 -1. 425 | <_> 426 | 13 4 3 3 3. 427 | 0 428 | -4.9458951689302921e-003 429 | 6.1991941928863525e-001 430 | -6.1633539199829102e-001 431 | <_> 432 | 433 | <_> 434 | 435 | 436 | 437 | <_> 438 | 40 4 10 4 -1. 439 | <_> 440 | 45 4 5 4 2. 441 | 0 442 | -5.1894597709178925e-003 443 | 4.4975179433822632e-001 444 | -8.0651968717575073e-001 445 | <_> 446 | 447 | <_> 448 | 449 | 450 | 451 | <_> 452 | 17 14 47 2 -1. 453 | <_> 454 | 17 15 47 1 2. 455 | 0 456 | -1.8824130296707153e-002 457 | 6.1992841958999634e-001 458 | -5.5643159151077271e-001 459 | <_> 460 | 461 | <_> 462 | 463 | 464 | 465 | <_> 466 | 8 5 4 7 -1. 467 | <_> 468 | 10 5 2 7 2. 469 | 0 470 | 5.6571601890027523e-003 471 | -4.8346561193466187e-001 472 | 6.8647360801696777e-001 473 | -2.2358059883117676e+000 474 | 4 475 | -1 476 | <_> 477 | 478 | 479 | <_> 480 | 481 | <_> 482 | 483 | 484 | 485 | <_> 486 | 56 0 6 6 -1. 487 | <_> 488 | 56 0 3 3 2. 489 | <_> 490 | 59 3 3 3 2. 491 | 0 492 | -9.1503243893384933e-003 493 | 6.8174481391906738e-001 494 | -7.7866071462631226e-001 495 | <_> 496 | 497 | <_> 498 | 499 | 500 | 501 | <_> 502 | 0 0 6 6 -1. 503 | <_> 504 | 0 0 3 3 2. 505 | <_> 506 | 3 3 3 3 2. 507 | 0 508 | 7.4933180585503578e-003 509 | -6.8696027994155884e-001 510 | 6.6913938522338867e-001 511 | <_> 512 | 513 | <_> 514 | 515 | 516 | 517 | <_> 518 | 13 4 48 2 -1. 519 | <_> 520 | 29 4 16 2 3. 521 | 0 522 | 4.5296419411897659e-002 523 | -7.3576509952545166e-001 524 | 5.9453499317169189e-001 525 | <_> 526 | 527 | <_> 528 | 529 | 530 | 531 | <_> 532 | 42 1 6 15 -1. 533 | <_> 534 | 42 6 6 5 3. 535 | 0 536 | 1.1669679544866085e-002 537 | -8.4733831882476807e-001 538 | 4.5461329817771912e-001 539 | <_> 540 | 541 | <_> 542 | 543 | 544 | 545 | <_> 546 | 30 8 3 5 -1. 547 | <_> 548 | 31 8 1 5 3. 549 | 0 550 | 2.5769430212676525e-003 551 | -5.8270388841629028e-001 552 | 7.7900522947311401e-001 553 | <_> 554 | 555 | <_> 556 | 557 | 558 | 559 | <_> 560 | 55 10 8 6 -1. 561 | <_> 562 | 55 13 8 3 2. 563 | 0 564 | -1.4139170525595546e-003 565 | 4.5126929879188538e-001 566 | -9.0696328878402710e-001 567 | -1.8782069683074951e+000 568 | 5 569 | -1 570 | <_> 571 | 572 | 573 | <_> 574 | 575 | <_> 576 | 577 | 578 | 579 | <_> 580 | 4 6 4 7 -1. 581 | <_> 582 | 6 6 2 7 2. 583 | 0 584 | -5.3149578161537647e-003 585 | 6.5218788385391235e-001 586 | -7.9464268684387207e-001 587 | <_> 588 | 589 | <_> 590 | 591 | 592 | 593 | <_> 594 | 56 3 6 8 -1. 595 | <_> 596 | 59 3 3 8 2. 597 | 0 598 | -2.2906960919499397e-002 599 | 6.6433382034301758e-001 600 | -7.3633247613906860e-001 601 | <_> 602 | 603 | <_> 604 | 605 | 606 | 607 | <_> 608 | 37 2 4 6 -1. 609 | <_> 610 | 37 4 4 2 3. 611 | 0 612 | 9.4887977465987206e-003 613 | -8.2612031698226929e-001 614 | 4.9333500862121582e-001 615 | <_> 616 | 617 | <_> 618 | 619 | 620 | 621 | <_> 622 | 0 10 30 6 -1. 623 | <_> 624 | 0 12 30 2 3. 625 | 0 626 | 4.5138411223888397e-002 627 | -5.4704028367996216e-001 628 | 7.6927912235260010e-001 629 | <_> 630 | 631 | <_> 632 | 633 | 634 | 635 | <_> 636 | 0 4 21 12 -1. 637 | <_> 638 | 7 4 7 12 3. 639 | 0 640 | 2.5049019604921341e-002 641 | -8.6739641427993774e-001 642 | 5.2807968854904175e-001 643 | -1.0597369670867920e+000 644 | 6 645 | -1 646 | <_> 647 | 648 | 649 | <_> 650 | 651 | <_> 652 | 653 | 654 | 655 | <_> 656 | 44 0 1 14 -1. 657 | <_> 658 | 44 7 1 7 2. 659 | 0 660 | 6.6414438188076019e-003 661 | -7.7290147542953491e-001 662 | 6.9723731279373169e-001 663 | <_> 664 | 665 | <_> 666 | 667 | 668 | 669 | <_> 670 | 54 3 4 3 -1. 671 | <_> 672 | 56 3 2 3 2. 673 | 0 674 | 2.4703629314899445e-003 675 | -7.4289917945861816e-001 676 | 6.6825848817825317e-001 677 | <_> 678 | 679 | <_> 680 | 681 | 682 | 683 | <_> 684 | 32 0 30 6 -1. 685 | <_> 686 | 32 0 15 3 2. 687 | <_> 688 | 47 3 15 3 2. 689 | 0 690 | -2.2910499945282936e-002 691 | 4.3986389040946960e-001 692 | -9.0588808059692383e-001 693 | <_> 694 | 695 | <_> 696 | 697 | 698 | 699 | <_> 700 | 0 8 9 7 -1. 701 | <_> 702 | 3 8 3 7 3. 703 | 0 704 | 3.4193221479654312e-002 705 | -6.9507479667663574e-001 706 | 6.2501090764999390e-001 707 | <_> 708 | 709 | <_> 710 | 711 | 712 | 713 | <_> 714 | 30 10 3 3 -1. 715 | <_> 716 | 31 10 1 3 3. 717 | 0 718 | 1.5060020377859473e-003 719 | -6.8670761585235596e-001 720 | 8.2241541147232056e-001 721 | <_> 722 | 723 | <_> 724 | 725 | 726 | 727 | <_> 728 | 21 3 24 4 -1. 729 | <_> 730 | 29 3 8 4 3. 731 | 0 732 | 1.9838380467263050e-005 733 | -9.2727631330490112e-001 734 | 6.4723730087280273e-001 735 | <_> 736 | 737 | <_> 738 | 739 | 740 | 741 | <_> 742 | 42 3 12 6 -1. 743 | <_> 744 | 46 3 4 6 3. 745 | 0 746 | -2.2170299416757189e-005 747 | 5.6555831432342529e-001 748 | -9.6788132190704346e-001 749 | -1.4993519783020020e+000 750 | 7 751 | -1 752 | <_> 753 | 754 | 755 | <_> 756 | 757 | <_> 758 | 759 | 760 | 761 | <_> 762 | 56 9 6 6 -1. 763 | <_> 764 | 59 9 3 6 2. 765 | 0 766 | -1.1395259760320187e-002 767 | 7.1383631229400635e-001 768 | -8.7429678440093994e-001 769 | <_> 770 | 771 | <_> 772 | 773 | 774 | 775 | <_> 776 | 6 4 1 6 -1. 777 | <_> 778 | 6 7 1 3 2. 779 | 0 780 | -2.1864590235054493e-003 781 | 8.5311782360076904e-001 782 | -6.4777731895446777e-001 783 | <_> 784 | 785 | <_> 786 | 787 | 788 | 789 | <_> 790 | 0 0 12 4 -1. 791 | <_> 792 | 0 0 6 2 2. 793 | <_> 794 | 6 2 6 2 2. 795 | 0 796 | 2.3193720262497663e-003 797 | -7.6411879062652588e-001 798 | 7.1867972612380981e-001 799 | <_> 800 | 801 | <_> 802 | 803 | 804 | 805 | <_> 806 | 43 12 18 2 -1. 807 | <_> 808 | 52 12 9 2 2. 809 | 0 810 | -7.9916073009371758e-003 811 | 6.6442942619323730e-001 812 | -7.9540950059890747e-001 813 | <_> 814 | 815 | <_> 816 | 817 | 818 | 819 | <_> 820 | 9 5 2 8 -1. 821 | <_> 822 | 10 5 1 8 2. 823 | 0 824 | 1.4212740352377295e-003 825 | -6.3904231786727905e-001 826 | 7.5050598382949829e-001 827 | -8.4829801321029663e-001 828 | 8 829 | -1 830 | <_> 831 | 832 | 833 | <_> 834 | 835 | <_> 836 | 837 | 838 | 839 | <_> 840 | 1 9 6 3 -1. 841 | <_> 842 | 3 9 2 3 3. 843 | 0 844 | 6.4091659151017666e-003 845 | -8.8425230979919434e-001 846 | 9.9953681230545044e-001 847 | <_> 848 | 849 | <_> 850 | 851 | 852 | 853 | <_> 854 | 56 8 2 8 -1. 855 | <_> 856 | 56 12 2 4 2. 857 | 0 858 | -6.3316390151157975e-004 859 | 8.3822172880172729e-001 860 | -9.8322170972824097e-001 861 | <_> 862 | 863 | <_> 864 | 865 | 866 | 867 | <_> 868 | 24 2 6 13 -1. 869 | <_> 870 | 26 2 2 13 3. 871 | 0 872 | -6.4947169448714703e-005 873 | 1. 874 | -9.1822808980941772e-001 875 | <_> 876 | 877 | <_> 878 | 879 | 880 | 881 | <_> 882 | 33 7 24 4 -1. 883 | <_> 884 | 41 7 8 4 3. 885 | 0 886 | 5.3404141217470169e-003 887 | -9.4317251443862915e-001 888 | 9.0425151586532593e-001 889 | -6.0007210820913315e-002 890 | 9 891 | -1 892 | <_> 893 | 894 | 895 | <_> 896 | 897 | <_> 898 | 899 | 900 | 901 | <_> 902 | 1 1 57 4 -1. 903 | <_> 904 | 1 3 57 2 2. 905 | 0 906 | 1.0755469650030136e-001 907 | -7.1647202968597412e-001 908 | 8.7827038764953613e-001 909 | <_> 910 | 911 | <_> 912 | 913 | 914 | 915 | <_> 916 | 0 2 6 14 -1. 917 | <_> 918 | 3 2 3 14 2. 919 | 0 920 | 3.1668949872255325e-002 921 | -8.7051069736480713e-001 922 | 5.8807212114334106e-001 923 | <_> 924 | 925 | <_> 926 | 927 | 928 | 929 | <_> 930 | 52 3 6 10 -1. 931 | <_> 932 | 54 3 2 10 3. 933 | 0 934 | -1.0572380386292934e-002 935 | 6.2438100576400757e-001 936 | -7.4027371406555176e-001 937 | <_> 938 | 939 | <_> 940 | 941 | 942 | 943 | <_> 944 | 1 14 61 2 -1. 945 | <_> 946 | 1 15 61 1 2. 947 | 0 948 | -2.7396259829401970e-002 949 | 8.9776748418807983e-001 950 | -5.2986758947372437e-001 951 | <_> 952 | 953 | <_> 954 | 955 | 956 | 957 | <_> 958 | 28 0 11 12 -1. 959 | <_> 960 | 28 4 11 4 3. 961 | 0 962 | 2.5918649509549141e-002 963 | -8.6482518911361694e-001 964 | 5.3121817111968994e-001 965 | -9.6125108003616333e-001 966 | 10 967 | -1 968 | <_> 969 | 970 | 971 | <_> 972 | 973 | <_> 974 | 975 | 976 | 977 | <_> 978 | 22 1 41 4 -1. 979 | <_> 980 | 22 3 41 2 2. 981 | 0 982 | 7.1039132773876190e-002 983 | -7.5719678401947021e-001 984 | 7.5645631551742554e-001 985 | <_> 986 | 987 | <_> 988 | 989 | 990 | 991 | <_> 992 | 41 6 6 8 -1. 993 | <_> 994 | 43 6 2 8 3. 995 | 0 996 | 7.6241148635745049e-003 997 | -7.9783838987350464e-001 998 | 7.1733069419860840e-001 999 | <_> 1000 | 1001 | <_> 1002 | 1003 | 1004 | 1005 | <_> 1006 | 50 9 14 5 -1. 1007 | <_> 1008 | 57 9 7 5 2. 1009 | 0 1010 | -2.7092639356851578e-002 1011 | 6.0071170330047607e-001 1012 | -8.4794402122497559e-001 1013 | <_> 1014 | 1015 | <_> 1016 | 1017 | 1018 | 1019 | <_> 1020 | 4 1 12 5 -1. 1021 | <_> 1022 | 10 1 6 5 2. 1023 | 0 1024 | -8.1267888890579343e-004 1025 | 5.9364068508148193e-001 1026 | -8.9295238256454468e-001 1027 | <_> 1028 | 1029 | <_> 1030 | 1031 | 1032 | 1033 | <_> 1034 | 37 9 3 3 -1. 1035 | <_> 1036 | 38 9 1 3 3. 1037 | 0 1038 | 8.3705072756856680e-004 1039 | -6.4887362718582153e-001 1040 | 7.8537952899932861e-001 1041 | -1.0618970394134521e+000 1042 | 11 1043 | -1 1044 | <_> 1045 | 1046 | 1047 | <_> 1048 | 1049 | <_> 1050 | 1051 | 1052 | 1053 | <_> 1054 | 54 0 10 6 -1. 1055 | <_> 1056 | 54 0 5 3 2. 1057 | <_> 1058 | 59 3 5 3 2. 1059 | 0 1060 | -9.7556859254837036e-003 1061 | 7.6982218027114868e-001 1062 | -8.5293501615524292e-001 1063 | <_> 1064 | 1065 | <_> 1066 | 1067 | 1068 | 1069 | <_> 1070 | 47 0 6 11 -1. 1071 | <_> 1072 | 49 0 2 11 3. 1073 | 0 1074 | -8.6617246270179749e-003 1075 | 8.4029090404510498e-001 1076 | -7.1949690580368042e-001 1077 | <_> 1078 | 1079 | <_> 1080 | 1081 | 1082 | 1083 | <_> 1084 | 19 2 20 2 -1. 1085 | <_> 1086 | 19 3 20 1 2. 1087 | 0 1088 | 1.6897840425372124e-002 1089 | -5.3601992130279541e-001 1090 | 9.5484441518783569e-001 1091 | <_> 1092 | 1093 | <_> 1094 | 1095 | 1096 | 1097 | <_> 1098 | 14 4 6 11 -1. 1099 | <_> 1100 | 17 4 3 11 2. 1101 | 0 1102 | 4.7526158596156165e-005 1103 | -7.6412862539291382e-001 1104 | 7.5398761034011841e-001 1105 | <_> 1106 | 1107 | <_> 1108 | 1109 | 1110 | 1111 | <_> 1112 | 31 9 33 2 -1. 1113 | <_> 1114 | 42 9 11 2 3. 1115 | 0 1116 | 6.5607670694589615e-003 1117 | -9.9346441030502319e-001 1118 | 6.4864277839660645e-001 1119 | -7.3307347297668457e-001 1120 | 12 1121 | -1 1122 | <_> 1123 | 1124 | 1125 | <_> 1126 | 1127 | <_> 1128 | 1129 | 1130 | 1131 | <_> 1132 | 6 1 53 6 -1. 1133 | <_> 1134 | 6 3 53 2 3. 1135 | 0 1136 | 1.0103269666433334e-001 1137 | -7.3275578022003174e-001 1138 | 8.4619927406311035e-001 1139 | <_> 1140 | 1141 | <_> 1142 | 1143 | 1144 | 1145 | <_> 1146 | 49 9 4 6 -1. 1147 | <_> 1148 | 49 9 2 3 2. 1149 | <_> 1150 | 51 12 2 3 2. 1151 | 0 1152 | -2.8920811018906534e-004 1153 | 7.1564781665802002e-001 1154 | -8.8221758604049683e-001 1155 | <_> 1156 | 1157 | <_> 1158 | 1159 | 1160 | 1161 | <_> 1162 | 0 9 30 7 -1. 1163 | <_> 1164 | 10 9 10 7 3. 1165 | 0 1166 | 1.0838840156793594e-002 1167 | -8.7420248985290527e-001 1168 | 6.0648679733276367e-001 1169 | <_> 1170 | 1171 | <_> 1172 | 1173 | 1174 | 1175 | <_> 1176 | 40 4 6 2 -1. 1177 | <_> 1178 | 42 4 2 2 3. 1179 | 0 1180 | 5.0803890917450190e-004 1181 | -9.0554022789001465e-001 1182 | 6.4213967323303223e-001 1183 | <_> 1184 | 1185 | <_> 1186 | 1187 | 1188 | 1189 | <_> 1190 | 1 9 6 1 -1. 1191 | <_> 1192 | 3 9 2 1 3. 1193 | 0 1194 | 2.3357039317488670e-003 1195 | -9.2574918270111084e-001 1196 | 8.6384928226470947e-001 1197 | <_> 1198 | 1199 | <_> 1200 | 1201 | 1202 | 1203 | <_> 1204 | 47 3 4 10 -1. 1205 | <_> 1206 | 47 8 4 5 2. 1207 | 0 1208 | 8.0239427916239947e-005 1209 | -9.9618428945541382e-001 1210 | 9.5355111360549927e-001 1211 | <_> 1212 | 1213 | <_> 1214 | 1215 | 1216 | 1217 | <_> 1218 | 31 5 30 11 -1. 1219 | <_> 1220 | 41 5 10 11 3. 1221 | 0 1222 | 3.2030208967626095e-003 1223 | -1. 1224 | 1.0001050233840942e+000 1225 | <_> 1226 | 1227 | <_> 1228 | 1229 | 1230 | 1231 | <_> 1232 | 0 0 2 1 -1. 1233 | <_> 1234 | 1 0 1 1 2. 1235 | 0 1236 | 0. 1237 | 0. 1238 | -1. 1239 | <_> 1240 | 1241 | <_> 1242 | 1243 | 1244 | 1245 | <_> 1246 | 21 3 42 5 -1. 1247 | <_> 1248 | 35 3 14 5 3. 1249 | 0 1250 | 2.6143440045416355e-003 1251 | -1. 1252 | 1.0002139806747437e+000 1253 | <_> 1254 | 1255 | <_> 1256 | 1257 | 1258 | 1259 | <_> 1260 | 0 0 2 1 -1. 1261 | <_> 1262 | 1 0 1 1 2. 1263 | 0 1264 | 0. 1265 | 0. 1266 | -1. 1267 | <_> 1268 | 1269 | <_> 1270 | 1271 | 1272 | 1273 | <_> 1274 | 8 5 30 9 -1. 1275 | <_> 1276 | 8 8 30 3 3. 1277 | 0 1278 | -7.0475979009643197e-004 1279 | 1. 1280 | -9.9976968765258789e-001 1281 | <_> 1282 | 1283 | <_> 1284 | 1285 | 1286 | 1287 | <_> 1288 | 3 12 33 3 -1. 1289 | <_> 1290 | 14 12 11 3 3. 1291 | 0 1292 | 2.1271279547363520e-003 1293 | -9.9694627523422241e-001 1294 | 1.0002720355987549e+000 1295 | <_> 1296 | 1297 | <_> 1298 | 1299 | 1300 | 1301 | <_> 1302 | 0 0 3 2 -1. 1303 | <_> 1304 | 1 0 1 2 3. 1305 | 0 1306 | -2.4224430671893060e-004 1307 | 1. 1308 | -1. 1309 | <_> 1310 | 1311 | <_> 1312 | 1313 | 1314 | 1315 | <_> 1316 | 46 4 3 8 -1. 1317 | <_> 1318 | 47 4 1 8 3. 1319 | 0 1320 | 7.4700301047414541e-004 1321 | -9.9108231067657471e-001 1322 | 9.9941182136535645e-001 1323 | -1.0991690158843994e+000 1324 | 13 1325 | -1 1326 | <_> 1327 | 1328 | 1329 | <_> 1330 | 1331 | <_> 1332 | 1333 | 1334 | 1335 | <_> 1336 | 1 2 6 5 -1. 1337 | <_> 1338 | 3 2 2 5 3. 1339 | 0 1340 | 1.7227890202775598e-003 1341 | -9.3608891963958740e-001 1342 | 8.7251222133636475e-001 1343 | <_> 1344 | 1345 | <_> 1346 | 1347 | 1348 | 1349 | <_> 1350 | 0 3 18 5 -1. 1351 | <_> 1352 | 6 3 6 5 3. 1353 | 0 1354 | 2.7599320746958256e-003 1355 | -9.9757021665573120e-001 1356 | 1.0000289678573608e+000 1357 | <_> 1358 | 1359 | <_> 1360 | 1361 | 1362 | 1363 | <_> 1364 | 3 1 6 14 -1. 1365 | <_> 1366 | 6 1 3 14 2. 1367 | 0 1368 | -8.9444358309265226e-005 1369 | 1. 1370 | -9.9264812469482422e-001 1371 | <_> 1372 | 1373 | <_> 1374 | 1375 | 1376 | 1377 | <_> 1378 | 3 6 2 10 -1. 1379 | <_> 1380 | 3 11 2 5 2. 1381 | 0 1382 | -2.7962020249105990e-004 1383 | 8.2833290100097656e-001 1384 | -9.8444151878356934e-001 1385 | <_> 1386 | 1387 | <_> 1388 | 1389 | 1390 | 1391 | <_> 1392 | 42 0 4 6 -1. 1393 | <_> 1394 | 42 0 2 3 2. 1395 | <_> 1396 | 44 3 2 3 2. 1397 | 0 1398 | -2.7560539820115082e-005 1399 | 1. 1400 | -9.9543339014053345e-001 1401 | -9.1314977407455444e-001 1402 | 14 1403 | -1 1404 | 1405 | -------------------------------------------------------------------------------- /3_face_detection/code/3.1_face_detection.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | 5 | ''' 6 | 7 | created on 08:29:27 2018-11-16 8 | 9 | @author:ren_dong 10 | 11 | haar级联分类器实现静态图像人脸检测 12 | 13 | 1、准备人脸、非人脸样本集; 14 | 15 | 2、计算特征值和积分图; 16 | 17 | 3、筛选出T个优秀的特征值(即最优弱分类器); 18 | 19 | 4、把这个T个最优弱分类器传给AdaBoost进行训练。 20 | 21 | 5、级联,也就是强分类器的强强联手。 22 | 23 | cv2.CascadeClassifier([filename]) → 24 | 25 | cv2.CascadeClassifier.detectMultiScale(image[, scaleFactor[, minNeighbors[, flags[, minSize[, maxSize]]]]]) → objects 26 | 27 | ''' 28 | filename = './images/face1.jpg' 29 | 30 | def detect(filename): 31 | 32 | #声明face_cascade对象,该变量为cascadeclassifier对象,它负责人脸检测 33 | face_cascade = cv2.CascadeClassifier('./cascade/haarcascade_frontalface_default.xml') 34 | 35 | img= cv2.imread(filename) 36 | 37 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 38 | 39 | 40 | # 进行人脸检测,传入scaleFactor,minNegihbors,分别表示人脸检测过程中每次迭代时图像的压缩率以及 41 | # 每个人脸矩形保留近似数目的最小值 42 | 43 | # 返回人脸矩形数组 44 | face = face_cascade.detectMultiScale(gray, 1.3, 5) 45 | 46 | for (x, y, w, h) in face: 47 | 48 | #绘制矩形 49 | img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2 ) 50 | 51 | #创建窗口 52 | cv2.namedWindow('face_detection') 53 | 54 | cv2.imshow('face_detection', img) 55 | 56 | cv2.waitKey() 57 | 58 | cv2.destroyAllWindows() 59 | 60 | 61 | if __name__ == '__main__': 62 | detect(filename) -------------------------------------------------------------------------------- /3_face_detection/code/3.2_face_video.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | 5 | ''' 6 | 7 | created on 19:18:27 2018-11-16 8 | 9 | @author:ren_dong 10 | 11 | haar级联分类器实现视频中的人脸检测 12 | 13 | 打开摄像头,读取帧,检测帧中的人脸,扫描检测到的人脸中的眼睛,对人脸绘制蓝色的矩形框,对人眼绘制绿色的矩形框 14 | 15 | 16 | cv2.CascadeClassifier([filename]) → 17 | 18 | cv2.CascadeClassifier.detectMultiScale(image[, scaleFactor[, minNeighbors[, flags[, minSize[, maxSize]]]]] 19 | 20 | 21 | ''' 22 | 23 | 24 | def DynamicDetect(): 25 | 26 | # 创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器. 27 | face_cascade = cv2.CascadeClassifier('./cascade/haarcascade_frontalface_default.xml') 28 | 29 | eye_cascade = cv2.CascadeClassifier('./cascade/haarcascade_eye.xml') 30 | 31 | # 打开摄像头 32 | camera = cv2.VideoCapture(0) 33 | cv2.namedWindow('Dynamic') 34 | 35 | while (True): 36 | # 读取一帧图像 37 | ret, frame = camera.read() 38 | # 判断图片读取成功? 39 | #rect()函数会返回两个值,第一个值是布尔值,用来表明是否成功读取帧,第二个为帧本身 40 | if ret: 41 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 42 | # 人脸检测 43 | faces = face_cascade.detectMultiScale(gray, 1.3, 5) 44 | for (x, y, w, h) in faces: 45 | # 在原图像上绘制矩形 46 | cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) 47 | roi_gray = gray[y:y + h, x:x + w] 48 | # 眼睛检测 49 | eyes = eye_cascade.detectMultiScale(roi_gray, 1.03, 5, 0, (40, 40)) 50 | for (ex, ey, ew, eh) in eyes: 51 | cv2.rectangle(frame, (ex + x, ey + y), (x + ex + ew, y + ey + eh), (0, 255, 0), 2) 52 | 53 | cv2.imshow('Dynamic', frame) 54 | # 如果按下q键则退出 55 | if cv2.waitKey(100) & 0xff == ord('q'): 56 | break 57 | 58 | camera.release() 59 | cv2.destroyAllWindows() 60 | 61 | 62 | if __name__ == '__main__': 63 | # filename = './image/img23.jpg' 64 | # StaticDetect(filename) 65 | DynamicDetect() 66 | 67 | -------------------------------------------------------------------------------- /3_face_detection/code/3.3.1_face_recognition.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | import os 5 | ''' 6 | 7 | created on 10:24:27 2018-11-18 8 | 9 | @author:ren_dong 10 | 11 | 人脸识别 调用摄像头进行个人头像数据采集,作为数据库 12 | 13 | 只是在原来检测人脸目标框的基础上,添加了resize()函数进行图像的resize, 14 | 然后调用imwrite()函数进行保存到指定路径下 15 | 16 | ''' 17 | 18 | def Generate_name(): 19 | 20 | # data = input('data:') 21 | # 22 | # name = input('input your name:') 23 | # 24 | # path = os.path.join(data, name) 25 | # 26 | # if os.path.isdir(path): 27 | # os.remove(path) 28 | # os.removedirs(path) 29 | 30 | # 31 | # os.mkdir(path) 32 | 33 | face_cascade = cv2.CascadeClassifier('./cascade/haarcascade_frontalface_default.xml') 34 | 35 | camera = cv2.VideoCapture(0) 36 | cv2.namedWindow('myself') 37 | count = 1 38 | 39 | while(True): 40 | 41 | ret, frame = camera.read() 42 | 43 | if ret: 44 | gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 45 | 46 | faces = cv2.CascadeClassifier.detectMultiScale(face_cascade, gray, 1.3, 5) 47 | 48 | for (x, y, w, h) in faces: 49 | cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) 50 | 51 | f = cv2.resize(gray[y:y+h, x:x+w], (92, 112)) 52 | 53 | cv2.imwrite('./data/ren_dong/%s.pgm' % str(count), f) 54 | 55 | count += 1 56 | 57 | cv2.imshow('myself', frame) 58 | 59 | if cv2.waitKey(35) & 0xff == ord('q'): 60 | break 61 | 62 | camera.release() 63 | cv2.destroyAllWindows() 64 | 65 | if __name__ == '__main__': 66 | Generate_name() -------------------------------------------------------------------------------- /3_face_detection/code/3.3.2_trainset.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | import os 5 | 6 | ''' 7 | 8 | created on 10:24:27 2018-11-18 9 | 10 | @author:ren_dong 11 | 12 | 人脸识别 13 | 利用数据进行数据集制作 14 | 15 | ''' 16 | 17 | 18 | # 2、读取ORL人脸数据库 准备训练数据 19 | def LoadImages(data): 20 | ''' 21 | 加载数据集 22 | params: 23 | data:训练集数据所在的目录,要求数据尺寸大小一样 24 | ret: 25 | images:[m,height,width] m为样本数,height为高,width为宽 26 | names:名字的集合 27 | labels:标签 28 | ''' 29 | images = [] 30 | labels = [] 31 | names = [] 32 | 33 | label = 0 34 | # 过滤所有的文件夹 35 | for subDirname in os.listdir(data): 36 | 37 | subjectPath = os.path.join(data, subDirname) 38 | #subjectpath即每一类所在的文件夹 39 | if os.path.isdir(subjectPath): 40 | # 每一个文件夹下存放着一个人的照片 41 | names.append(subDirname) 42 | ##得到图片名字filename 43 | 44 | for fileName in os.listdir(subjectPath): 45 | #路径拼接,得到图片路径 46 | imgPath = os.path.join(subjectPath, fileName) 47 | #遍历路径按照文件名 读取图片 48 | img = cv2.imread(imgPath, cv2.IMREAD_GRAYSCALE) 49 | #添加images 50 | images.append(img) 51 | #添加label 52 | labels.append(label) 53 | label += 1 54 | images = np.asarray(images) 55 | labels = np.asarray(labels) 56 | return images, labels, names 57 | 58 | 59 | if __name__ == '__main__': 60 | data = './data' 61 | LoadImages(data) -------------------------------------------------------------------------------- /3_face_detection/code/3.3.3_recognition.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | import os 5 | import shutil 6 | 7 | ''' 8 | 9 | created on 10:24:27 2018-11-18 10 | 11 | @author:ren_dong 12 | 13 | 人脸识别 调用摄像头进行个人头像数据采集,作为数据库 14 | 15 | 只是在原来检测人脸目标框的基础上,添加了resize()函数进行图像的resize, 16 | 然后调用imwrite()函数进行保存到指定路径下 17 | 18 | ''' 19 | 20 | # -*- coding: utf-8 -*- 21 | """ 22 | Created on Thu Aug 16 19:41:19 2018 23 | 24 | @author: lenovo 25 | """ 26 | 27 | ''' 28 | 调用opencv库实现人脸识别 29 | ''' 30 | 31 | # 读取pgm图像,并显示 32 | def ShowPgm(filepath): 33 | cv2.namedWindow('pgm') 34 | img = cv2.imread(filepath) 35 | cv2.imshow('pgm', img) 36 | print(img.shape) 37 | cv2.waitKey(0) 38 | cv2.destroyAllWindows() 39 | 40 | # 2、读取ORL人脸数据库 准备训练数据 41 | def LoadImages(data): 42 | ''' 43 | 加载数据集 44 | params: 45 | data:训练集数据所在的目录,要求数据尺寸大小一样 46 | ret: 47 | images:[m,height,width] m为样本数,height为高,width为宽 48 | names:名字的集合 49 | labels:标签 50 | ''' 51 | images = [] 52 | labels = [] 53 | names = [] 54 | 55 | label = 0 56 | # 过滤所有的文件夹 57 | for subDirname in os.listdir(data): 58 | 59 | subjectPath = os.path.join(data, subDirname) 60 | #subjectpath即每一类所在的文件夹 61 | if os.path.isdir(subjectPath): 62 | # 每一个文件夹下存放着一个人的照片 63 | names.append(subDirname) 64 | ##得到图片名字filename 65 | 66 | for fileName in os.listdir(subjectPath): 67 | #路径拼接,得到图片路径 68 | imgPath = os.path.join(subjectPath, fileName) 69 | #遍历路径按照文件名 读取图片 70 | img = cv2.imread(imgPath, cv2.IMREAD_GRAYSCALE) 71 | #添加images 72 | images.append(img) 73 | #添加label 74 | labels.append(label) 75 | label += 1 76 | images = np.asarray(images) 77 | labels = np.asarray(labels) 78 | return images, labels, names 79 | 80 | 81 | def FaceRec(data): 82 | # 加载训练数据 83 | X, y, names = LoadImages('./data') 84 | 85 | 86 | model = cv2.face.EigenFaceRecognizer_create() 87 | model.train(X, y) 88 | 89 | # 创建一个级联分类器 加载一个 .xml 分类器文件. 它既可以是Haar特征也可以是LBP特征的分类器. 90 | face_cascade = cv2.CascadeClassifier('./cascade/haarcascade_frontalface_default.xml') 91 | 92 | # 打开摄像头 93 | camera = cv2.VideoCapture(0) 94 | cv2.namedWindow('Dynamic') 95 | 96 | while (True): 97 | # 读取一帧图像 98 | ret, frame = camera.read() 99 | # 判断图片读取成功? 100 | if ret: 101 | gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 102 | # 人脸检测 103 | 104 | faces = face_cascade.detectMultiScale(gray_img, 1.3, 5) 105 | for (x, y, w, h) in faces: 106 | # 在原图像上绘制矩形 107 | frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) 108 | roi_gray = gray_img[y:y + h, x:x + w] 109 | 110 | try: 111 | # 宽92 高112 112 | roi_gray = cv2.resize(roi_gray, (92, 112), interpolation=cv2.INTER_LINEAR) 113 | params = model.predict(roi_gray) 114 | print('Label:%s,confidence:%.2f' % (params[0], params[1])) 115 | cv2.putText(frame, names[params[0]], (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2) 116 | except: 117 | continue 118 | 119 | cv2.imshow('Dynamic', frame) 120 | # 如果按下q键则退出 121 | if cv2.waitKey(100) & 0xff == ord('q'): 122 | break 123 | camera.release() 124 | cv2.destroyAllWindows() 125 | 126 | 127 | if __name__ == '__main__': 128 | # ShowPgm('./face/s1/1.pgm') 129 | data = './data' 130 | # 生成自己的人脸数据 131 | # generator(data) 132 | FaceRec(data) -------------------------------------------------------------------------------- /3_face_detection/code/Readme: -------------------------------------------------------------------------------- 1 | The code stores the program that calls the Haar classifier for face detection, 2 | 3 | including detecting face detection in still images and videos. 4 | -------------------------------------------------------------------------------- /3_face_detection/data/S1/1.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/data/S1/1.pgm -------------------------------------------------------------------------------- /3_face_detection/data/S1/10.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/data/S1/10.pgm -------------------------------------------------------------------------------- /3_face_detection/data/S1/2.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/data/S1/2.pgm -------------------------------------------------------------------------------- /3_face_detection/data/S1/3.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/data/S1/3.pgm -------------------------------------------------------------------------------- /3_face_detection/data/S1/4.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/data/S1/4.pgm -------------------------------------------------------------------------------- /3_face_detection/data/S1/5.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/data/S1/5.pgm -------------------------------------------------------------------------------- /3_face_detection/data/S1/6.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/data/S1/6.pgm -------------------------------------------------------------------------------- /3_face_detection/data/S1/7.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/data/S1/7.pgm -------------------------------------------------------------------------------- /3_face_detection/data/S1/8.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/data/S1/8.pgm -------------------------------------------------------------------------------- /3_face_detection/data/S1/9.pgm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/data/S1/9.pgm -------------------------------------------------------------------------------- /3_face_detection/data/S1/Readme: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /3_face_detection/data/ren_dong/Readme: -------------------------------------------------------------------------------- 1 | This store is a personal picture, a total of ten, suffixed with .pgm 2 | -------------------------------------------------------------------------------- /3_face_detection/images/Readme: -------------------------------------------------------------------------------- 1 | Images store test images for static face detection 2 | -------------------------------------------------------------------------------- /3_face_detection/images/face1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/images/face1.jpg -------------------------------------------------------------------------------- /3_face_detection/images/face2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/images/face2.jpg -------------------------------------------------------------------------------- /3_face_detection/output/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/3_face_detection/output/1.png -------------------------------------------------------------------------------- /4_Feature matching/code/4.1_Harris.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | import os 3 | import cv2 4 | import numpy as np 5 | ''' 6 | created on 08:05:10 2018-11-20 7 | @author ren_dong 8 | 9 | 使用cornerHarris进行角点检测 10 | 11 | cv2.cornerHarris(src, blockSize, ksize, k[, dst[, borderType]]) → dst 12 | 13 | 14 | ''' 15 | img = cv2.imread('chess.jpg') 16 | 17 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 18 | 19 | gray= np.float32(gray) 20 | 21 | #第三个参数定义了角点检测的敏感度,其值必须是介于3和31之间的奇数 22 | ##dst为函数返回的浮点值图像,其中包含角点检测结果 23 | #第二个参数值决定了标记角点的记号大小,参数值越小,记号越小 24 | dst = cv2.cornerHarris(gray, 4, 23, 0.04) 25 | print dst.shape 26 | #在原图进行标记 阈值 27 | img[dst > 0.01*dst.max()] = [0, 0, 255] 28 | 29 | while(True): 30 | 31 | cv2.imshow('Harris', img) 32 | if cv2.waitKey(100) & 0xff == ord('q'): 33 | break 34 | 35 | cv2.destroyAllWindows() 36 | -------------------------------------------------------------------------------- /4_Feature matching/code/4.2_SIFT.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import os 3 | import cv2 4 | import numpy as np 5 | 6 | ''' 7 | created on 08:05:10 2018-11-20 8 | @author ren_dong 9 | 10 | 使用DoG和SIFT进行特征提取和描述 11 | 12 | cv2.SIFT.detectAndCompute(image, mask[, descriptors[, useProvidedKeypoints]]) → keypoints, descriptors 13 | 14 | cv2.drawKeypoints(image, keypoints[, outImage[, color[, flags]]]) → outImage 15 | 16 | 首先创建了一个SIFT对象,SIFT对象会使用DoG检测关键点,并且对每个关键点周围区域计算特征向量。 17 | detectAndCompute()函数会返回关键点信息(每一个元素都是一个对象,有兴趣的可以看一下OpenCV源码)和关键点的描述符。 18 | 然后,我们在图像上绘制关键点,并显示出来。 19 | 20 | ''' 21 | img = cv2.imread('chess.jpg') 22 | 23 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 24 | 25 | #创建sift对象 26 | sift = cv2.xfeatures2d.SIFT_create() 27 | 28 | #进行检测和计算 返回特征点信息和描述符 29 | keypoints , descriptor = sift.detectAndCompute(gray, None) 30 | #keypoints:特征点集合list,向量内每一个元素是一个KeyPoint对象,包含了特征点的各种属性信息; 31 | 32 | 33 | 34 | #绘制关键点 35 | img = cv2.drawKeypoints(img, keypoints=keypoints, outImage=img, color= (51, 163, 236), flags= cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 36 | 37 | #sift得到的图像为128维的特征向量集 38 | 39 | print len(keypoints) 40 | print descriptor.shape 41 | 42 | cv2.imshow('sift_keypoints',img) 43 | cv2.waitKey() 44 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /4_Feature matching/code/4.3_SURF.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import os 3 | import cv2 4 | import numpy as np 5 | 6 | ''' 7 | created on 09:05:10 2018-11-22 8 | @author ren_dong 9 | 10 | 使用快速Hessian算法和SURF来提取和检测特征 11 | 12 | ''' 13 | img = cv2.imread('chess.jpg') 14 | 15 | gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 16 | 17 | #创建一个SURF对象 18 | surf = cv2.xfeatures2d.SURF_create(20000) 19 | #SURF算法使用Hessian算法计算关键点,并且在关键点周围区域计算特征向量,该函数返回关键点的信息和描述符 20 | keypoints, descriptor = surf.detectAndCompute(gray, None) 21 | print descriptor.shape 22 | print len(keypoints) 23 | 24 | img = cv2.drawKeypoints(image=img, outImage=img, keypoints=keypoints, flags=4, color=(51, 163, 236)) 25 | 26 | cv2.imshow('SURF', img) 27 | 28 | cv2.waitKey() 29 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /4_Feature matching/code/4.4_fast.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Aug 27 16:09:48 2018 4 | 5 | @author: lenovo 6 | """ 7 | 8 | ''' 9 | FAST角点检测 10 | ''' 11 | import cv2 12 | 13 | '''1、加载图片''' 14 | img1 = cv2.imread('chess.jpg') 15 | img1 = cv2.resize(img1,dsize=(600,400)) 16 | image1 = img1.copy() 17 | 18 | 19 | '''2、提取特征点''' 20 | #创建一个FAST对象,传入阈值t 可以处理RGB色彩空间图像 21 | fast = cv2.FastFeatureDetector_create(threshold=50) 22 | keypoints1 = fast.detect(image1,None) 23 | #在图像上绘制关键点 24 | image1 = cv2.drawKeypoints(image=image1,keypoints = keypoints1,outImage=image1,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 25 | 26 | #输出默认参数 27 | print("Threshold: ", fast.getThreshold()) 28 | print("nonmaxSuppression: ", fast.getNonmaxSuppression()) 29 | print("neighborhood: ", fast.getType()) 30 | print("Total Keypoints with nonmaxSuppression: ", len(keypoints1)) 31 | 32 | #显示图像 33 | cv2.imshow('fast_keypoints1',image1) 34 | cv2.waitKey(20) 35 | 36 | #关闭非极大值抑制 37 | fast.setNonmaxSuppression(0) 38 | keypoints1 = fast.detect(image1,None) 39 | print("Total Keypoints without nonmaxSuppression: ", len(keypoints1)) 40 | image1 = cv2.drawKeypoints(image=image1,keypoints = keypoints1,outImage=image1,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 41 | cv2.imshow('fast_keypoints1 nms',image1) 42 | 43 | cv2.waitKey(0) 44 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /4_Feature matching/code/4.5_ORB.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import os 3 | import cv2 4 | import numpy as np 5 | 6 | ''' 7 | created on 09:05:10 2018-11-22 8 | @author ren_dong 9 | 10 | 使用ORB特征匹配 11 | 12 | ''' 13 | def orb_test(): 14 | # 加载图片 灰色 15 | img1 = cv2.imread('orb1.jpg') 16 | gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) 17 | img2 = cv2.imread('orb2.jpg') 18 | img2 = cv2.resize(img2, dsize=(450, 300)) 19 | gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) 20 | image1 = gray1.copy() 21 | image2 = gray2.copy() 22 | 23 | ''' 24 | 1.使用ORB算法检测特征点、描述符 25 | ''' 26 | orb = cv2.ORB_create(128) 27 | keypoints1, descriptors1 = orb.detectAndCompute(image1, None) 28 | keypoints2, descriptors2 = orb.detectAndCompute(image2, None) 29 | # 在图像上绘制关键点 30 | image1 = cv2.drawKeypoints(image=image1, keypoints=keypoints1, outImage=image1, color=(255, 0, 255), 31 | flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 32 | image2 = cv2.drawKeypoints(image=image2, keypoints=keypoints2, outImage=image2, color=(255, 0, 255), 33 | flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 34 | # 显示图像 35 | cv2.imshow('orb_keypoints1', image1) 36 | cv2.imshow('orb_keypoints2', image2) 37 | cv2.waitKey(20) 38 | 39 | ''' 40 | 2、匹配 41 | ''' 42 | matcher = cv2.BFMatcher_create(cv2.HAMMING_NORM_TYPE, crossCheck=True) 43 | matchePoints = matcher.match(descriptors1, descriptors2) 44 | print(type(matchePoints), len(matchePoints), matchePoints[0]) 45 | # 按照距离从小到大排序,选取最优匹配的 46 | sorted(matchePoints, key=lambda x: x.distance) 47 | # 绘制最优匹配点 48 | outImg = None 49 | outImg = cv2.drawMatches(img1, keypoints1, img2, keypoints2, matchePoints[:40], outImg, matchColor=(0, 255, 0), 50 | flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT) 51 | cv2.imshow('matche', outImg) 52 | cv2.waitKey(0) 53 | cv2.destroyAllWindows() 54 | 55 | cv2.waitKey(0) 56 | cv2.destroyAllWindows() 57 | 58 | 59 | if __name__ == '__main__': 60 | orb_test() -------------------------------------------------------------------------------- /4_Feature matching/code/4.6_KNN.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import os 3 | import cv2 4 | import numpy as np 5 | 6 | ''' 7 | created on 09:05:10 2018-11-22 8 | @author ren_dong 9 | 10 | 使用KNN即K近邻算法进行特征匹配 11 | ORB算法 12 | 13 | ''' 14 | 15 | img1 = cv2.imread('orb1.jpg',0) #测试图像img1 16 | # img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) 17 | img2 = cv2.imread('orb2.jpg',0) ##训练图像img2 18 | # img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) 19 | 20 | orb = cv2.ORB_create() 21 | kp1, des1 = orb.detectAndCompute(img1, None) 22 | kp2, des2 = orb.detectAndCompute(img2, None) 23 | 24 | bf = cv2.BFMatcher(cv2.NORM_HAMMING,crossCheck = False) 25 | #对每个匹配选择两个最佳的匹配 26 | matches = bf.knnMatch(des1, des2, k=2) 27 | 28 | print(type(matches), len(matches), matches[0]) 29 | 30 | # 获取img1中的第一个描述符即[0][]在img2中最匹配即[0][0]的一个描述符 距离最小 31 | dMatch0 = matches[0][0] 32 | 33 | # 获取img1中的第一个描述符在img2中次匹配的一个描述符 距离次之 34 | dMatch1 = matches[0][1] 35 | print('knnMatches', dMatch0.distance, dMatch0.queryIdx, dMatch0.trainIdx) 36 | print('knnMatches', dMatch1.distance, dMatch1.queryIdx, dMatch1.trainIdx) 37 | # 将不满足的最近邻的匹配之间距离比率大于设定的阈值匹配剔除。 38 | 39 | img3 = None 40 | img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, img3, flags=cv2.DRAW_MATCHES_FLAGS_DEFAULT) 41 | img3 = cv2.resize(img3,(1000, 400)) 42 | cv2.imshow('KNN',img3) 43 | cv2.waitKey() 44 | cv2.destroyAllWindows() 45 | 46 | -------------------------------------------------------------------------------- /4_Feature matching/code/4.7_FLANN.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import os 3 | import cv2 4 | import numpy as np 5 | 6 | ''' 7 | created on 09:05:10 2018-11-22 8 | @author ren_dong 9 | 10 | 使用FLANN特征匹配 11 | 12 | ''' 13 | def flann_test(): 14 | ''' 15 | FLANN匹配 16 | ''' 17 | # 加载图片 灰色 18 | img1 = cv2.imread('orb1.jpg') 19 | gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) 20 | img2 = cv2.imread('orb2.jpg') 21 | img2 = cv2.resize(img2, dsize=(450, 300)) 22 | gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) 23 | queryImage = gray1.copy() 24 | trainImage = gray2.copy() 25 | 26 | # 创建SIFT对象 27 | sift = cv2.xfeatures2d.SIFT_create(100) 28 | # SIFT对象会使用DoG检测关键点,并且对每个关键点周围的区域计算特征向量。该函数返回关键点的信息和描述符 29 | keypoints1, descriptor1 = sift.detectAndCompute(queryImage, None) 30 | keypoints2, descriptor2 = sift.detectAndCompute(trainImage, None) 31 | print('descriptor1:', descriptor1.shape, 'descriptor2', descriptor2.shape) 32 | # 在图像上绘制关键点 33 | queryImage = cv2.drawKeypoints(image=queryImage, keypoints=keypoints1, outImage=queryImage, color=(255, 0, 255), 34 | flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 35 | trainImage = cv2.drawKeypoints(image=trainImage, keypoints=keypoints2, outImage=trainImage, color=(255, 0, 255), 36 | flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 37 | # 显示图像 38 | # cv2.imshow('sift_keypoints1',queryImage) 39 | # cv2.imshow('sift_keypoints2',trainImage) 40 | # cv2.waitKey(20) 41 | 42 | # FLANN匹配 43 | FLANN_INDEX_KDTREE = 0 44 | indexParams = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) 45 | searchParams = dict(checks=50) 46 | flann = cv2.FlannBasedMatcher(indexParams, searchParams) 47 | #indexParams, searchParams 48 | matches = flann.knnMatch(descriptor1, descriptor2, k=2) 49 | 50 | print(type(matches), len(matches), matches[0]) 51 | # 获取queryImage中的第一个描述符在trainingImage中最匹配的一个描述符 距离最小 52 | dMatch0 = matches[0][0] 53 | # 获取queryImage中的第一个描述符在trainingImage中次匹配的一个描述符 距离次之 54 | dMatch1 = matches[0][1] 55 | print('knnMatches', dMatch0.distance, dMatch0.queryIdx, dMatch0.trainIdx) 56 | print('knnMatches', dMatch1.distance, dMatch1.queryIdx, dMatch1.trainIdx) 57 | 58 | # 设置mask,过滤匹配点 作用和上面那个一样 59 | matchesMask = [[0, 0] for i in range(len(matches))] 60 | 61 | minRatio = 1 / 3 62 | for i, (m, n) in enumerate(matches): 63 | if m.distance / n.distance < minRatio: 64 | matchesMask[i] = [1, 0] # 只绘制最优匹配点 65 | 66 | drawParams = dict( # singlePointColor=(255,0,0),matchColor=(0,255,0), 67 | matchesMask=matchesMask, 68 | flags=0) 69 | resultImage = cv2.drawMatchesKnn(queryImage, keypoints1, trainImage, keypoints2, matches, 70 | None, **drawParams) 71 | 72 | cv2.imshow('matche', resultImage) 73 | cv2.waitKey(0) 74 | cv2.destroyAllWindows() 75 | 76 | 77 | if __name__ == '__main__': 78 | flann_test() -------------------------------------------------------------------------------- /4_Feature matching/code/4.8_danyingxing.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Sep 15 13:22:10 2018 4 | 5 | @author: zy 6 | """ 7 | 8 | ''' 9 | 单应性匹配 10 | ''' 11 | 12 | import numpy as np 13 | import cv2 14 | 15 | 16 | def flann_hom_test(): 17 | # 加载图像 18 | img1 = cv2.imread('orb1.jpg') # queryImage 19 | img2 = cv2.imread('orb2.jpg') # trainImage 20 | gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) 21 | gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) 22 | 23 | # img2 = cv2.resize(img2,dsize=(450,600)) 24 | 25 | MIN_MATCH_COUNT = 10 26 | 27 | ''' 28 | 1.使用SIFT算法检测特征点、描述符 29 | ''' 30 | sift = cv2.xfeatures2d.SIFT_create(100) 31 | kp1, des1 = sift.detectAndCompute(gray1, None) 32 | kp2, des2 = sift.detectAndCompute(gray2, None) 33 | # 在图像上绘制关键点 34 | # img1 = cv2.drawKeypoints(image=img1,keypoints = kp1,outImage=img1,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 35 | # img2 = cv2.drawKeypoints(image=img2,keypoints = kp2,outImage=img2,color=(255,0,255),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) 36 | # 显示图像 37 | # cv2.imshow('sift_keypoints1',img1) 38 | # cv2.imshow('sift_keypoints2',img2) 39 | # cv2.waitKey(20) 40 | 41 | ''' 42 | 2、FLANN匹配 43 | ''' 44 | FLANN_INDEX_KDTREE = 0 45 | indexParams = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) 46 | searchParams = dict(checks=50) 47 | flann = cv2.FlannBasedMatcher(indexParams, searchParams) 48 | matches = flann.knnMatch(des1, des2, k=2) 49 | 50 | # 将不满足的最近邻的匹配之间距离比率大于设定的阈值匹配剔除。 51 | goodMatches = [] 52 | minRatio = 0.7 53 | for m, n in matches: 54 | if m.distance / n.distance < minRatio: 55 | goodMatches.append(m) # 注意 如果使用drawMatches 则不用写成List类型[m] 56 | 57 | ''' 58 | 3、单应性变换 59 | ''' 60 | # 确保至少有一定数目的良好匹配(理论上,计算单应性至少需要4对匹配点,实际上会使用10对以上的匹配点) 61 | if len(goodMatches) > MIN_MATCH_COUNT: 62 | # 获取匹配点坐标 63 | src_pts = np.float32([kp1[m.queryIdx].pt for m in goodMatches]).reshape(-1, 2) 64 | dst_pts = np.float32([kp2[m.trainIdx].pt for m in goodMatches]).reshape(-1, 2) 65 | 66 | print('src_pts:', len(src_pts), src_pts[0]) 67 | print('dst_pts:', len(dst_pts), dst_pts[0]) 68 | 69 | # 获取单应性:即一个平面到另一个平面的映射矩阵 70 | M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) 71 | # print('M:',M,type(M)) # [3,3] 72 | matchesMask = mask.ravel().tolist() # 用来配置匹配图,只绘制单应性图片中关键点的匹配线 73 | # 由于使用的是drawMatches绘制匹配线,这里list 74 | # 每个元素也是一个标量,并不是一个list 75 | print('matchesMask:', len(matchesMask), matchesMask[0]) 76 | 77 | # 计算原始图像img1中书的四个顶点的投影畸变,并在目标图像img2上绘制边框 78 | h, w = img1.shape[:2] 79 | # 源图片中书的的四个角点 80 | pts = np.float32([[55, 74], [695, 45], [727, 464], [102, 548]]).reshape(-1, 1, 2) 81 | print('pts:', pts.shape) 82 | dst = cv2.perspectiveTransform(pts, M) 83 | print('dst:', dst.shape) 84 | # 在img2上绘制边框 85 | img2 = cv2.polylines(img2, [np.int32(dst)], True, (0, 255, 0), 2, cv2.LINE_AA) 86 | 87 | else: 88 | print("Not enough matches are found - %d/%d" % (len(goodMatches), MIN_MATCH_COUNT)) 89 | matchesMask = None 90 | 91 | ''' 92 | 绘制显示效果 93 | ''' 94 | draw_params = dict(matchColor=(0, 255, 0), # draw matches in green color 95 | singlePointColor=None, 96 | matchesMask=matchesMask, # draw only inliers 97 | flags=2) 98 | 99 | img3 = cv2.drawMatches(img1, kp1, img2, kp2, goodMatches, None, **draw_params) 100 | cv2.imshow('matche', img3) 101 | cv2.waitKey(0) 102 | cv2.destroyAllWindows() 103 | 104 | 105 | if __name__ == '__main__': 106 | flann_hom_test() -------------------------------------------------------------------------------- /4_Feature matching/code/readme: -------------------------------------------------------------------------------- 1 | This file is used to store the code 2 | -------------------------------------------------------------------------------- /4_Feature matching/images/chess.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/4_Feature matching/images/chess.jpg -------------------------------------------------------------------------------- /4_Feature matching/images/orb1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/4_Feature matching/images/orb1.jpg -------------------------------------------------------------------------------- /4_Feature matching/images/orb2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/4_Feature matching/images/orb2.jpg -------------------------------------------------------------------------------- /4_Feature matching/images/readme: -------------------------------------------------------------------------------- 1 | This file is used to store images 2 | -------------------------------------------------------------------------------- /4_Feature matching/readme: -------------------------------------------------------------------------------- 1 | This chapter describes how to use opencv to detect image features 2 | 3 | and use these features for image matching and searching. 4 | -------------------------------------------------------------------------------- /5_face_recognition/readme: -------------------------------------------------------------------------------- 1 | 记录自己对face_recognition 人脸识别库的简单应用 2 | 3 | 包括人脸绘制轮廓 4 | 5 | 6 | 7 | 8 | 9 | 提取图片人脸 10 | 11 | 12 | 13 | 14 | 美妆 15 | -------------------------------------------------------------------------------- /5_object_detection/code/5.1_person_detect.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Sep 24 09:17:37 2018 4 | 5 | @author: ren_dong 6 | """ 7 | 8 | ''' 9 | HOG检测人 10 | ''' 11 | import cv2 12 | import numpy as np 13 | 14 | 15 | def is_inside(o, i): 16 | ''' 17 | 判断矩形o是不是在i矩形中 18 | 19 | args: 20 | o:矩形o (x,y,w,h) 21 | i:矩形i (x,y,w,h) 22 | ''' 23 | ox, oy, ow, oh = o 24 | ix, iy, iw, ih = i 25 | return ox > ix and oy > iy and ox + ow < ix + iw and oy + oh < iy + ih 26 | 27 | 28 | def draw_person(img, person): 29 | ''' 30 | 在img图像上绘制矩形框person 31 | 32 | args: 33 | img:图像img 34 | person:人所在的边框位置 (x,y,w,h) 35 | ''' 36 | x, y, w, h = person 37 | cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2) 38 | 39 | 40 | def detect_test(): 41 | ''' 42 | 检测人 43 | ''' 44 | img = cv2.imread('./images/person.jpg') 45 | rows, cols = img.shape[:2] 46 | sacle = 0.5 47 | print('img',img.shape) 48 | img = cv2.resize(img, dsize=(int(cols * sacle), int(rows * sacle))) 49 | # print('img',img.shape) 50 | # img = cv2.resize(img, (128,64)) 51 | 52 | # 创建HOG描述符对象 53 | # 计算一个检测窗口特征向量维度:(64/8 - 1)*(128/8 - 1)*4*9 = 3780 54 | ''' 55 | winSize = (64,128) 56 | blockSize = (16,16) 57 | blockStride = (8,8) 58 | cellSize = (8,8) 59 | nbins = 9 60 | hog = cv2.HOGDescriptor(winSize,blockSize,blockStride,cellSize,nbins) 61 | ''' 62 | hog = cv2.HOGDescriptor() 63 | # hist = hog.compute(img[0:128,0:64]) 计算一个检测窗口的维度 64 | # print(hist.shape) 65 | detector = cv2.HOGDescriptor_getDefaultPeopleDetector() 66 | print('detector', type(detector), detector.shape) 67 | hog.setSVMDetector(detector) 68 | 69 | # 多尺度检测,found是一个数组,每一个元素都是对应一个矩形,即检测到的目标框 70 | found, w = hog.detectMultiScale(img) 71 | print('found', type(found), found.shape) 72 | 73 | # 过滤一些矩形,如果矩形o在矩形i中,则过滤掉o 74 | found_filtered = [] 75 | for ri, r in enumerate(found): 76 | for qi, q in enumerate(found): 77 | # r在q内? 78 | if ri != qi and is_inside(r, q): 79 | break 80 | else: 81 | found_filtered.append(r) 82 | 83 | for person in found_filtered: 84 | draw_person(img, person) 85 | 86 | cv2.imshow('img', img) 87 | cv2.waitKey() 88 | cv2.destroyAllWindows() 89 | 90 | 91 | if __name__ == '__main__': 92 | detect_test() -------------------------------------------------------------------------------- /5_object_detection/code/5.2_HOG.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Sep 24 18:23:04 2018 4 | 5 | @author: zy 6 | """ 7 | 8 | # 代码来源GitHub:https://github.com/PENGZhaoqing/Hog-feature 9 | # https://blog.csdn.net/ppp8300885/article/details/71078555 10 | # https://www.leiphone.com/news/201708/ZKsGd2JRKr766wEd.html 11 | 12 | import cv2 13 | import numpy as np 14 | import math 15 | import matplotlib.pyplot as plt 16 | 17 | 18 | class Hog_descriptor(): 19 | ''' 20 | HOG描述符的实现 21 | ''' 22 | 23 | def __init__(self, img, cell_size=8, bin_size=9): 24 | ''' 25 | 构造函数 26 | 默认参数,一个block由2x2个cell组成,步长为1个cell大小 27 | args: 28 | img:输入图像(更准确的说是检测窗口),这里要求为灰度图像 对于行人检测图像大小一般为128x64 即是输入图像上的一小块裁切区域 29 | cell_size:细胞单元的大小 如8,表示8x8个像素 30 | bin_size:直方图的bin个数 31 | ''' 32 | self.img = img 33 | ''' 34 | 采用Gamma校正法对输入图像进行颜色空间的标准化(归一化),目的是调节图像的对比度,降低图像局部 35 | 的阴影和光照变化所造成的影响,同时可以抑制噪音。采用的gamma值为0.5。 f(I)=I^γ 36 | ''' 37 | self.img = np.sqrt(img * 1.0 / float(np.max(img))) 38 | self.img = self.img * 255 39 | # print('img',self.img.dtype) #float64 40 | # 参数初始化 41 | self.cell_size = cell_size 42 | self.bin_size = bin_size 43 | self.angle_unit = 180 / self.bin_size # 这里采用180° 44 | assert type(self.bin_size) == int, "bin_size should be integer," 45 | assert type(self.cell_size) == int, "cell_size should be integer," 46 | assert 180 % self.bin_size == 0, "bin_size should be divisible by 180" 47 | 48 | def extract(self): 49 | ''' 50 | 计算图像的HOG描述符,以及HOG-image特征图 51 | ''' 52 | height, width = self.img.shape 53 | ''' 54 | 1、计算图像每一个像素点的梯度幅值和角度 55 | ''' 56 | gradient_magnitude, gradient_angle = self.global_gradient() 57 | gradient_magnitude = abs(gradient_magnitude) 58 | ''' 59 | 2、计算输入图像的每个cell单元的梯度直方图,形成每个cell的descriptor 比如输入图像为128x64 可以得到16x8个cell,每个cell由9个bin组成 60 | ''' 61 | cell_gradient_vector = np.zeros((int(height / self.cell_size), int(width / self.cell_size), self.bin_size)) 62 | # 遍历每一行、每一列 63 | for i in range(cell_gradient_vector.shape[0]): 64 | for j in range(cell_gradient_vector.shape[1]): 65 | # 计算第[i][j]个cell的特征向量 66 | cell_magnitude = gradient_magnitude[i * self.cell_size:(i + 1) * self.cell_size, 67 | j * self.cell_size:(j + 1) * self.cell_size] 68 | cell_angle = gradient_angle[i * self.cell_size:(i + 1) * self.cell_size, 69 | j * self.cell_size:(j + 1) * self.cell_size] 70 | cell_gradient_vector[i][j] = self.cell_gradient(cell_magnitude, cell_angle) 71 | 72 | # 将得到的每个cell的梯度方向直方图绘出,得到特征图 73 | hog_image = self.render_gradient(np.zeros([height, width]), cell_gradient_vector) 74 | 75 | ''' 76 | 3、将2x2个cell组成一个block,一个block内所有cell的特征串联起来得到该block的HOG特征descriptor 77 | 将图像image内所有block的HOG特征descriptor串联起来得到该image(检测目标)的HOG特征descriptor, 78 | 这就是最终分类的特征向量 79 | ''' 80 | hog_vector = [] 81 | # 默认步长为一个cell大小,一个block由2x2个cell组成,遍历每一个block 82 | for i in range(cell_gradient_vector.shape[0] - 1): 83 | for j in range(cell_gradient_vector.shape[1] - 1): 84 | # 提取第[i][j]个block的特征向量 85 | block_vector = [] 86 | block_vector.extend(cell_gradient_vector[i][j]) 87 | block_vector.extend(cell_gradient_vector[i][j + 1]) 88 | block_vector.extend(cell_gradient_vector[i + 1][j]) 89 | block_vector.extend(cell_gradient_vector[i + 1][j + 1]) 90 | '''块内归一化梯度直方图,去除光照、阴影等变化,增加鲁棒性''' 91 | # 计算l2范数 92 | mag = lambda vector: math.sqrt(sum(i ** 2 for i in vector)) 93 | magnitude = mag(block_vector) + 1e-5 94 | # 归一化 95 | if magnitude != 0: 96 | normalize = lambda block_vector, magnitude: [element / magnitude for element in block_vector] 97 | block_vector = normalize(block_vector, magnitude) 98 | hog_vector.append(block_vector) 99 | return np.asarray(hog_vector), hog_image 100 | 101 | def global_gradient(self): 102 | ''' 103 | 分别计算图像沿x轴和y轴的梯度 104 | ''' 105 | gradient_values_x = cv2.Sobel(self.img, cv2.CV_64F, 1, 0, ksize=5) 106 | gradient_values_y = cv2.Sobel(self.img, cv2.CV_64F, 0, 1, ksize=5) 107 | # 计算梯度幅值 这个计算的是0.5*gradient_values_x + 0.5*gradient_values_y 108 | # gradient_magnitude = cv2.addWeighted(gradient_values_x, 0.5, gradient_values_y, 0.5, 0) 109 | # 计算梯度方向 110 | # gradient_angle = cv2.phase(gradient_values_x, gradient_values_y, angleInDegrees=True) 111 | gradient_magnitude, gradient_angle = cv2.cartToPolar(gradient_values_x, gradient_values_y, angleInDegrees=True) 112 | # 角度大于180°的,减去180度 113 | gradient_angle[gradient_angle > 180.0] -= 180 114 | # print('gradient',gradient_magnitude.shape,gradient_angle.shape,np.min(gradient_angle),np.max(gradient_angle)) 115 | return gradient_magnitude, gradient_angle 116 | 117 | def cell_gradient(self, cell_magnitude, cell_angle): 118 | ''' 119 | 为每个细胞单元构建梯度方向直方图 120 | 121 | args: 122 | cell_magnitude:cell中每个像素点的梯度幅值 123 | cell_angle:cell中每个像素点的梯度方向 124 | return: 125 | 返回该cell对应的梯度直方图,长度为bin_size 126 | ''' 127 | orientation_centers = [0] * self.bin_size 128 | # 遍历cell中的每一个像素点 129 | for i in range(cell_magnitude.shape[0]): 130 | for j in range(cell_magnitude.shape[1]): 131 | # 梯度幅值 132 | gradient_strength = cell_magnitude[i][j] 133 | # 梯度方向 134 | gradient_angle = cell_angle[i][j] 135 | # 双线性插值 136 | min_angle, max_angle, weight = self.get_closest_bins(gradient_angle) 137 | orientation_centers[min_angle] += (gradient_strength * (1 - weight)) 138 | orientation_centers[max_angle] += (gradient_strength * weight) 139 | return orientation_centers 140 | 141 | def get_closest_bins(self, gradient_angle): 142 | ''' 143 | 计算梯度方向gradient_angle位于哪一个bin中,这里采用的计算方式为双线性插值 144 | 具体参考:https://www.leiphone.com/news/201708/ZKsGd2JRKr766wEd.html 145 | 例如:当我们把180°划分为9个bin的时候,分别对应对应0,20,40,...160这些角度。 146 | 角度是10,副值是4,因为角度10介于0-20度的中间(正好一半),所以把幅值 147 | 一分为二地放到0和20两个bin里面去。 148 | args: 149 | gradient_angle:角度 150 | return: 151 | start,end,weight:起始bin索引,终止bin的索引,end索引对应bin所占权重 152 | ''' 153 | idx = int(gradient_angle / self.angle_unit) 154 | mod = gradient_angle % self.angle_unit 155 | return idx % self.bin_size, (idx + 1) % self.bin_size, mod / self.angle_unit 156 | 157 | def render_gradient(self, image, cell_gradient): 158 | ''' 159 | 将得到的每个cell的梯度方向直方图绘出,得到特征图 160 | args: 161 | image:画布,和输入图像一样大 [h,w] 162 | cell_gradient:输入图像的每个cell单元的梯度直方图,形状为[h/cell_size,w/cell_size,bin_size] 163 | return: 164 | image:特征图 165 | ''' 166 | cell_width = self.cell_size / 2 167 | max_mag = np.array(cell_gradient).max() 168 | # 遍历每一个cell 169 | for x in range(cell_gradient.shape[0]): 170 | for y in range(cell_gradient.shape[1]): 171 | # 获取第[i][j]个cell的梯度直方图 172 | cell_grad = cell_gradient[x][y] 173 | # 归一化 174 | cell_grad /= max_mag 175 | angle = 0 176 | angle_gap = self.angle_unit 177 | # 遍历每一个bin区间 178 | for magnitude in cell_grad: 179 | # 转换为弧度 180 | angle_radian = math.radians(angle) 181 | # 计算起始坐标和终点坐标,长度为幅值(归一化),幅值越大、绘制的线条越长、越亮 182 | x1 = int(x * self.cell_size + cell_width + magnitude * cell_width * math.cos(angle_radian)) 183 | y1 = int(y * self.cell_size + cell_width + magnitude * cell_width * math.sin(angle_radian)) 184 | x2 = int(x * self.cell_size + cell_width - magnitude * cell_width * math.cos(angle_radian)) 185 | y2 = int(y * self.cell_size + cell_width - magnitude * cell_width * math.sin(angle_radian)) 186 | cv2.line(image, (y1, x1), (y2, x2), int(255 * math.sqrt(magnitude))) 187 | angle += angle_gap 188 | return image 189 | 190 | 191 | if __name__ == '__main__': 192 | # 加载图像 193 | img = cv2.imread('./image/person.jpg') 194 | width = 64 195 | height = 128 196 | img_copy = img[320:320 + height, 570:570 + width][:, :, ::-1] 197 | gray_copy = cv2.cvtColor(img_copy, cv2.COLOR_BGR2GRAY) 198 | 199 | # 显示原图像 200 | plt.figure(figsize=(6.4, 2.0 * 3.2)) 201 | plt.subplot(1, 2, 1) 202 | plt.imshow(img_copy) 203 | 204 | # HOG特征提取 205 | hog = Hog_descriptor(gray_copy, cell_size=8, bin_size=9) 206 | hog_vector, hog_image = hog.extract() 207 | print('hog_vector', hog_vector.shape) 208 | print('hog_image', hog_image.shape) 209 | 210 | # 绘制特征图 211 | plt.subplot(1, 2, 2) 212 | plt.imshow(hog_image, cmap=plt.cm.gray) 213 | plt.show() -------------------------------------------------------------------------------- /5_object_detection/code/5.3_BOW.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Oct 17 09:38:26 2018 4 | 5 | @author: ren_dong 6 | """ 7 | 8 | ''' 9 | 词袋模型BOW+SVM 目标识别 10 | 11 | 以狗和猫数据集二分类为例 12 | 如果是狗 返回True 13 | 如果是猫 返回False 14 | ''' 15 | import numpy as np 16 | import cv2 17 | 18 | 19 | class BOW(object): 20 | 21 | def __init__(self, ): 22 | # 创建一个SIFT对象 用于关键点提取 23 | self.feature_detector = cv2.xfeatures2d.SIFT_create() 24 | # 创建一个SIFT对象 用于关键点描述符提取 25 | self.descriptor_extractor = cv2.xfeatures2d.SIFT_create() 26 | 27 | def path(self, cls, i): 28 | ''' 29 | 用于获取图片的全路径 30 | ''' 31 | # train_path/dog/dog.i.jpg 32 | return '%s/%s/%s.%d.jpg' % (self.train_path, cls, cls, i + 1) 33 | 34 | def fit(self, train_path, k): 35 | ''' 36 | 开始训练 37 | 38 | args: 39 | train_path:训练集图片路径 我们使用的数据格式为 train_path/dog/dog.i.jpg train_path/cat/cat.i.jpg 40 | k:k-means参数k 41 | ''' 42 | self.train_path = train_path 43 | 44 | # FLANN匹配 参数algorithm用来指定匹配所使用的算法,可以选择的有LinearIndex、KTreeIndex、KMeansIndex、CompositeIndex和AutotuneIndex,这里选择的是KTreeIndex(使用kd树实现最近邻搜索) 45 | flann_params = dict(algorithm=1, tree=5) 46 | flann = cv2.FlannBasedMatcher(flann_params, {}) 47 | 48 | # 创建BOW训练器,指定k-means参数k 把处理好的特征数据全部合并,利用聚类把特征词分为若干类,此若干类的数目由自己设定,每一类相当于一个视觉词汇 49 | bow_kmeans_trainer = cv2.BOWKMeansTrainer(k) 50 | 51 | pos = 'dog' 52 | neg = 'cat' 53 | 54 | # 指定用于提取词汇字典的样本数 55 | length = 10 56 | # 合并特征数据 每个类从数据集中读取length张图片(length个狗,length个猫),通过聚类创建视觉词汇 57 | for i in range(length): 58 | bow_kmeans_trainer.add(self.sift_descriptor_extractor(self.path(pos, i))) 59 | bow_kmeans_trainer.add(self.sift_descriptor_extractor(self.path(neg, i))) 60 | 61 | # 进行k-means聚类,返回词汇字典 也就是聚类中心 62 | voc = bow_kmeans_trainer.cluster() 63 | 64 | # 输出词汇字典 (40, 128) 65 | print(type(voc), voc.shape) 66 | 67 | # 初始化bow提取器(设置词汇字典),用于提取每一张图像的BOW特征描述 68 | self.bow_img_descriptor_extractor = cv2.BOWImgDescriptorExtractor(self.descriptor_extractor, flann) 69 | self.bow_img_descriptor_extractor.setVocabulary(voc) 70 | 71 | # 创建两个数组,分别对应训练数据和标签,并用BOWImgDescriptorExtractor产生的描述符填充 72 | # 按照下面的方法生成相应的正负样本图片的标签 1:正匹配 -1:负匹配 73 | traindata, trainlabels = [], [] 74 | for i in range(400): # 这里取200张图像做训练 75 | traindata.extend(self.bow_descriptor_extractor(self.path(pos, i))) 76 | trainlabels.append(1) 77 | traindata.extend(self.bow_descriptor_extractor(self.path(neg, i))) 78 | trainlabels.append(-1) 79 | 80 | # 创建一个SVM对象 81 | self.svm = cv2.ml.SVM_create() 82 | # 使用训练数据和标签进行训练 83 | self.svm.train(np.array(traindata), cv2.ml.ROW_SAMPLE, np.array(trainlabels)) 84 | 85 | def predict(self, img_path): 86 | ''' 87 | 进行预测样本 88 | ''' 89 | # 提取图片的BOW特征描述 90 | data = self.bow_descriptor_extractor(img_path) 91 | res = self.svm.predict(data) 92 | print(img_path, '\t', res[1][0][0]) 93 | 94 | # 如果是狗 返回True 95 | if res[1][0][0] == 1.0: 96 | return True 97 | # 如果是猫,返回False 98 | else: 99 | return False 100 | 101 | def sift_descriptor_extractor(self, img_path): 102 | ''' 103 | 特征提取:提取数据集中每幅图像的特征点,然后提取特征描述符,形成特征数据(如:SIFT或者SURF方法); 104 | ''' 105 | im = cv2.imread(img_path, 0) 106 | return self.descriptor_extractor.compute(im, self.feature_detector.detect(im))[1] 107 | 108 | def bow_descriptor_extractor(self, img_path): 109 | ''' 110 | 提取图像的BOW特征描述(即利用视觉词袋量化图像特征) 111 | ''' 112 | im = cv2.imread(img_path, 0) 113 | return self.bow_img_descriptor_extractor.compute(im, self.feature_detector.detect(im)) 114 | 115 | 116 | if __name__ == '__main__': 117 | # 测试样本数量,测试结果 118 | test_samples = 100 119 | test_results = np.zeros(test_samples, dtype=np.bool) 120 | 121 | # 训练集图片路径 狗和猫两类 进行训练 122 | train_path = './data/cat_and_dog/data/train' 123 | bow = BOW() 124 | bow.fit(train_path, 40) 125 | 126 | # 指定测试图像路径 127 | for index in range(test_samples): 128 | dog = './data/cat_and_dog/data/train/dog/dog.{0}.jpg'.format(index) 129 | dog_img = cv2.imread(dog) 130 | 131 | # 预测 132 | dog_predict = bow.predict(dog) 133 | test_results[index] = dog_predict 134 | 135 | # 计算准确率 136 | accuracy = np.mean(test_results.astype(dtype=np.float32)) 137 | print('测试准确率为:', accuracy) 138 | 139 | # 可视化最后一个 140 | font = cv2.FONT_HERSHEY_SIMPLEX 141 | if test_results[0]: 142 | cv2.putText(dog_img, 'Dog Detected', (10, 30), font, 1, (0, 255, 0), 2, cv2.LINE_AA) 143 | 144 | cv2.imshow('dog_img', dog_img) 145 | 146 | cv2.waitKey(0) 147 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /5_object_detection/code/readme: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /5_object_detection/images/person.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/5_object_detection/images/person.jpg -------------------------------------------------------------------------------- /5_object_detection/images/readme: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /5_object_detection/readme: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /6_object_traack/code/5.4_track.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | 3 | import cv2 4 | import numpy as np 5 | 6 | ''' 7 | 帧差法实现目标追踪 8 | @author 2019-1-22 19:56 9 | 10 | ''' 11 | camera = cv2.VideoCapture(0) 12 | 13 | es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9,4)) 14 | kernel = np.ones((5,5), np.uint8) 15 | background = None 16 | 17 | while(True): 18 | ret, frame = camera.read() 19 | if background is None: 20 | background = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 21 | background = cv2.GaussianBlur(background, (21,21), 0) 22 | continue 23 | 24 | 25 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 26 | gray_frame = cv2.GaussianBlur(gray_frame, (21, 21), 0) 27 | 28 | diff = cv2.absdiff(background, gray_frame) 29 | diff = cv2.threshold(diff, 25, 255, cv2.THRESH_BINARY)[1] 30 | diff = cv2.dilate(diff, es, iterations=2) 31 | 32 | image, cnts, hierarchy = cv2.findContours(diff.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 33 | 34 | for c in cnts: 35 | if cv2.contourArea(c) < 1500: 36 | continue 37 | (x, y, w, h) = cv2.boundingRect(c) 38 | cv2.rectangle(frame, (x,y), (x+w,y+h), (0, 255, 0), 2) 39 | 40 | cv2.imshow("contours", frame) 41 | cv2.imshow("diff", diff) 42 | if cv2.waitKey(50) & 0xff == ord("q"): 43 | break 44 | 45 | cv2.destroyAllWindows() 46 | camera.release() 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /6_object_traack/code/6.1_track.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | 3 | import cv2 4 | import numpy as np 5 | 6 | ''' 7 | 帧差法实现目标追踪 8 | @author 2019-1-22 19:56 9 | 10 | 第一帧设为背景--> frame灰度化+高斯模糊 -->计算差异-->寻找轮廓 设定阈值 -->绘框并显示 11 | 12 | ''' 13 | camera = cv2.VideoCapture(0) 14 | 15 | es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9,4)) 16 | kernel = np.ones((5,5), np.uint8) 17 | background = None 18 | 19 | while(True): 20 | ret, frame = camera.read() 21 | if background is None: 22 | background = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 23 | background = cv2.GaussianBlur(background, (21,21), 0) 24 | continue 25 | 26 | 27 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 28 | gray_frame = cv2.GaussianBlur(gray_frame, (21, 21), 0) 29 | 30 | diff = cv2.absdiff(background, gray_frame) 31 | diff = cv2.threshold(diff, 25, 255, cv2.THRESH_BINARY)[1] 32 | diff = cv2.dilate(diff, es, iterations=2) 33 | 34 | image, cnts, hierarchy = cv2.findContours(diff.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 35 | 36 | for c in cnts: 37 | if cv2.contourArea(c) < 1500: 38 | continue 39 | (x, y, w, h) = cv2.boundingRect(c) 40 | cv2.rectangle(frame, (x,y), (x+w,y+h), (0, 255, 0), 2) 41 | 42 | cv2.imshow("contours", frame) 43 | cv2.imshow("diff", diff) 44 | if cv2.waitKey(50) & 0xff == ord("q"): 45 | break 46 | 47 | cv2.destroyAllWindows() 48 | camera.release() 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /6_object_traack/code/6.2_KNN.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | 3 | import cv2 4 | import numpy as np 5 | ''' 6 | 背景分割器KNN实现运动检测 7 | @author 2018-1-23 18:53 8 | 9 | KNN -->阈值化去除阴影-->膨胀去粗白色斑点-->寻找轮廓-->绘框并显示 10 | ''' 11 | bs = cv2.createBackgroundSubtractorKNN(detectShadows = True) 12 | camera = cv2.VideoCapture('1.mp4') 13 | 14 | while True: 15 | ret, frame = camera.read() 16 | fgmask = bs.apply(frame) 17 | th = cv2.threshold(fgmask.copy(), 244, 255, cv2.THRESH_BINARY)[1] 18 | dilated = cv2.dilate(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3)), iterations = 2) 19 | 20 | image, contours, hier = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 21 | 22 | for c in contours: 23 | if cv2.contourArea(c) > 1600: 24 | (x, y, w, h) = cv2.boundingRect(c) 25 | cv2.rectangle(frame, (x, y), (x+w, y+h), (255,255,0), 2) 26 | 27 | cv2.imshow("mog", fgmask) 28 | cv2.imshow("thresh", th) 29 | cv2.imshow("detection", frame) 30 | 31 | if cv2.waitKey(30) & 0xff == 27: 32 | break 33 | camera.release() 34 | cv2.destroyAllWindows() -------------------------------------------------------------------------------- /6_object_traack/code/6.3_meanshift.py: -------------------------------------------------------------------------------- 1 | #-*- coding:utf-8 -*- 2 | import numpy as np 3 | import cv2 4 | ''' 5 | @author 2019-1-25 20:25 6 | Meanshift 均值漂移 7 | 8 | 标记感兴趣区域-->HSV空间 -->计算直方图+归一化 --> 反向投影 --> meanshift -->绘框并显示 9 | 10 | ''' 11 | 12 | #标记初始感兴趣的区域 13 | cap = cv2.VideoCapture(0) 14 | ret, frame = cap.read() 15 | r,h,c,w = 10, 200, 10, 20 16 | track_window = (c,r,w,h) 17 | 18 | roi = frame[r:r+h, c:c+w] 19 | #BGR ---> HSV 20 | hsv_roi = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 21 | 22 | #构建mask,给定array上下界 23 | mask = cv2.inRange(hsv_roi, np.array((100., 30, 32.)),np.array((180, 120, 255))) 24 | 25 | #计算直方图 26 | roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0,180]) 27 | 28 | #线性直方图归一化 29 | cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX) 30 | 31 | #设定meanshift迭代停止条件 32 | term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1) 33 | 34 | while True: 35 | ret, frame = cap.read() 36 | 37 | if ret == True: 38 | hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 39 | dst = cv2.calcBackProject([hsv], [0], roi_hist, [0,180], 1) 40 | 41 | #对ROI进行meanshift 给定window和停止条件 42 | ret, track_window = cv2.meanShift(dst, track_window, term_crit) 43 | 44 | #重新计算window 然后在原图绘制矩形框 45 | x,y,w,h = track_window 46 | img2 = cv2.rectangle(frame, (x,y), (x+w,y+h), 255, 2) 47 | cv2.imshow('img2', img2) 48 | 49 | k = cv2.waitKey(60) &0xff 50 | if k == 27: 51 | break 52 | else: 53 | break 54 | 55 | cv2.destroyAllWindows() 56 | cap.release() 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /6_object_traack/code/6.4_camshift.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | import numpy as np 3 | import cv2 4 | 5 | ''' 6 | @author 2019-1-25 21:07 7 | camshift 8 | 9 | 标记感兴趣区域-->HSV空间 -->计算直方图+归一化 --> 反向投影 --> camshift -->绘框并显示 10 | 11 | ''' 12 | 13 | # 标记初始感兴趣的区域 14 | cap = cv2.VideoCapture(0) 15 | ret, frame = cap.read() 16 | r, h, c, w = 10, 200, 10, 20 17 | track_window = (c, r, w, h) 18 | 19 | roi = frame[r:r + h, c:c + w] 20 | # BGR ---> HSV 21 | hsv_roi = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 22 | 23 | # 构建mask,给定array上下界 24 | mask = cv2.inRange(hsv_roi, np.array((100., 30, 32.)), np.array((180, 120, 255))) 25 | 26 | # 计算直方图 27 | roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180]) 28 | 29 | # 线性直方图归一化 30 | cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX) 31 | 32 | # 设定meanshift迭代停止条件 33 | term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1) 34 | 35 | while True: 36 | ret, frame = cap.read() 37 | 38 | if ret == True: 39 | hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) 40 | dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1) 41 | 42 | # 对ROI进行meanshift 给定window和停止条件 43 | ret, track_window = cv2.CamShift(dst, track_window, term_crit) 44 | #返回旋转矩形的四个顶点points 45 | pts = cv2.boxPoints(ret) 46 | pts = np.int0(pts) 47 | #绘制多边形曲线图 48 | img2 = cv2.polylines(frame, [pts], True, 255, 2) 49 | 50 | cv2.imshow('img2', img2) 51 | 52 | k = cv2.waitKey(60) & 0xff 53 | if k == 27: 54 | break 55 | else: 56 | break 57 | 58 | cv2.destroyAllWindows() 59 | cap.release() 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /6_object_traack/code/readme: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenCV_Notes 2 | 作为自己学习OpenCv的记录笔记 3 | 4 | 邮箱地址:17854257054@163.com 5 | 6 | 7 | ## Welcome star!!!!!! 8 | 9 | ### 一 图像预处理 10 | 11 | 图片读取 显示 保存 读取 12 | 13 | #### 模糊滤波 14 | 原图模糊滤波模糊滤波模糊滤波 15 | 16 | #### 轮廓检测 #### 多边形 直线检测 17 | 18 | 轮廓检测多边形检测 19 | 20 | #### 圆检测 21 | 22 | 圆检测 23 | 24 | ## 二 图像分割 25 | 26 | #### Grabcut算法 27 | Grabcut算法Grabcut算法 28 | 29 | #### 分水岭算法 30 | 31 | 原图分水岭算法分水岭算法分水岭算法 32 | 33 | ## 三 人脸检测 34 | 35 | 分水岭算法分水岭算法 36 | -------------------------------------------------------------------------------- /face_recognition/facial.py: -------------------------------------------------------------------------------- 1 | from PIL import Image, ImageDraw 2 | import face_recognition 3 | 4 | # Load the jpg file into a numpy array 5 | image = face_recognition.load_image_file("images/002.jpg") 6 | 7 | # Find all facial features in all the faces in the image 8 | face_landmarks_list = face_recognition.face_landmarks(image) 9 | 10 | print("I found {} face(s) in this photograph.".format(len(face_landmarks_list))) 11 | 12 | # Create a PIL imagedraw object so we can draw on the picture 13 | pil_image = Image.fromarray(image) 14 | d = ImageDraw.Draw(pil_image) 15 | 16 | for face_landmarks in face_landmarks_list: 17 | print face_landmarks.keys() 18 | # Print the location of each facial feature in this image 19 | for facial_feature in face_landmarks.keys(): 20 | print("The {} in this face has the following points: {}".format(facial_feature, face_landmarks[facial_feature])) 21 | 22 | # Let's trace out each facial feature in the image with a line! 23 | for facial_feature in face_landmarks.keys(): 24 | d.line(face_landmarks[facial_feature], fill=(255,0,255), width=2) 25 | 26 | # Show the picture 27 | pil_image.show() 28 | pil_image.save('images/11.jpg') -------------------------------------------------------------------------------- /face_recognition/find_face.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import face_recognition 3 | 4 | # Load the jpg file into a numpy array 5 | image = face_recognition.load_image_file("images/003.jpg") 6 | 7 | # Find all the faces in the image using the default HOG-based model. 8 | # This method is fairly accurate, but not as accurate as the CNN model and not GPU accelerated. 9 | 10 | face_locations = face_recognition.face_locations(image) 11 | # face_locations = face_recognition.face_locations(image, number_of_times_to_upsample=0, model="cnn") 12 | print("I found {} face(s) in this photograph.".format(len(face_locations))) 13 | 14 | for face_location in face_locations: 15 | 16 | # Print the location of each face in this image 17 | top, right, bottom, left = face_location 18 | print("A face is located at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}".format(top, left, bottom, right)) 19 | 20 | # You can access the actual face itself like this: 21 | face_image = image[top:bottom, left:right] 22 | pil_image = Image.fromarray(face_image) 23 | pil_image.show() -------------------------------------------------------------------------------- /face_recognition/find_face_cnn.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import face_recognition 3 | 4 | # Load the jpg file into a numpy array 5 | image = face_recognition.load_image_file("images/004.jpg") 6 | 7 | # Find all the faces in the image using a pre-trained convolutional neural network. 8 | # This method is more accurate than the default HOG model, but it's slower 9 | # unless you have an nvidia GPU and dlib compiled with CUDA extensions. But if you do, 10 | # this will use GPU acceleration and perform well. 11 | 12 | face_locations = face_recognition.face_locations(image, number_of_times_to_upsample=0, model="cnn") 13 | 14 | print("I found {} face(s) in this photograph.".format(len(face_locations))) 15 | 16 | for face_location in face_locations: 17 | 18 | # Print the location of each face in this image 19 | top, right, bottom, left = face_location 20 | print("A face is located at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}".format(top, left, bottom, right)) 21 | 22 | # You can access the actual face itself like this: 23 | face_image = image[top:bottom, left:right] 24 | pil_image = Image.fromarray(face_image) 25 | pil_image.show() -------------------------------------------------------------------------------- /face_recognition/images/001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/face_recognition/images/001.jpg -------------------------------------------------------------------------------- /face_recognition/images/002.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/face_recognition/images/002.jpg -------------------------------------------------------------------------------- /face_recognition/images/003.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/face_recognition/images/003.jpg -------------------------------------------------------------------------------- /face_recognition/images/004.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/face_recognition/images/004.jpg -------------------------------------------------------------------------------- /face_recognition/images/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/face_recognition/images/11.jpg -------------------------------------------------------------------------------- /face_recognition/images/22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/face_recognition/images/22.jpg -------------------------------------------------------------------------------- /face_recognition/images/33.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rendong3/OpenCV-Notes/937d8107d6e2418299fed062a1be07ac0e36bd0e/face_recognition/images/33.jpg -------------------------------------------------------------------------------- /face_recognition/images/readme: -------------------------------------------------------------------------------- 1 | 这里和往常一样, 存储以上程序用到的图片 2 | -------------------------------------------------------------------------------- /face_recognition/makeups.py: -------------------------------------------------------------------------------- 1 | from PIL import Image, ImageDraw 2 | import face_recognition 3 | 4 | # Load the jpg file into a numpy array 5 | image = face_recognition.load_image_file("images/004.jpg") 6 | 7 | # Find all facial features in all the faces in the image 8 | face_landmarks_list = face_recognition.face_landmarks(image) 9 | 10 | for face_landmarks in face_landmarks_list: 11 | pil_image = Image.fromarray(image) 12 | d = ImageDraw.Draw(pil_image, 'RGBA') 13 | 14 | # Make the eyebrows into a nightmare 15 | d.polygon(face_landmarks['left_eyebrow'], fill=(68, 54, 39, 128)) 16 | d.polygon(face_landmarks['right_eyebrow'], fill=(68, 54, 39, 128)) 17 | d.line(face_landmarks['left_eyebrow'], fill=(68, 54, 39, 150), width=5) 18 | d.line(face_landmarks['right_eyebrow'], fill=(68, 54, 39, 150), width=5) 19 | 20 | # Gloss the lips 21 | d.polygon(face_landmarks['top_lip'], fill=(150, 0, 0, 128)) 22 | d.polygon(face_landmarks['bottom_lip'], fill=(150, 0, 0, 128)) 23 | d.line(face_landmarks['top_lip'], fill=(150, 0, 0, 64), width=8) 24 | d.line(face_landmarks['bottom_lip'], fill=(150, 0, 0, 64), width=8) 25 | 26 | # Sparkle the eyes 27 | d.polygon(face_landmarks['left_eye'], fill=(255, 255, 255, 30)) 28 | d.polygon(face_landmarks['right_eye'], fill=(255, 255, 255, 30)) 29 | 30 | # Apply some eyeliner 31 | d.line(face_landmarks['left_eye'] + [face_landmarks['left_eye'][0]], fill=(0, 0, 0, 110), width=6) 32 | d.line(face_landmarks['right_eye'] + [face_landmarks['right_eye'][0]], fill=(0, 0, 0, 110), width=6) 33 | 34 | pil_image.show() -------------------------------------------------------------------------------- /face_recognition/profile.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | #绘制面部轮廓 3 | import cv2 4 | import face_recognition 5 | from PIL import Image, ImageDraw 6 | 7 | # 将图片文件加载到numpy 数组中 8 | img = cv2.imread('images/001.jpg') 9 | img1 = cv2.resize(img, (400,600), interpolation=cv2.INTER_CUBIC) 10 | cv2.imwrite('images/002.jpg',img1) 11 | image = face_recognition.load_image_file('images/002.jpg') 12 | 13 | #查找图像中所有面部的所有面部特征 14 | face_landmarks_list = face_recognition.face_landmarks(image) 15 | print("I found {} face(s) in this photograph.".format(len(face_landmarks_list))) 16 | 17 | for face_landmarks in face_landmarks_list: 18 | facial_features = [ 19 | 'chin', 'left_eyebrow', 'right_eyebrow', 'nose_bridge', 'nose_tip', 20 | 'left_eye', 'right_eye', 'top_lip', 'bottom_lip' 21 | ] 22 | pil_image = Image.fromarray(image) 23 | 24 | d = ImageDraw.Draw(pil_image) 25 | 26 | for facial_feature in facial_features: 27 | d.line(face_landmarks[facial_feature], fill=(0, 255, 0), width=2) 28 | print("The {} in this face has the following points: {}".format(facial_feature, face_landmarks[facial_feature])) 29 | 30 | pil_image.show() 31 | 32 | -------------------------------------------------------------------------------- /face_recognition/readme: -------------------------------------------------------------------------------- 1 | 记录对于face_recongnition人脸识别库的简单应用 2 | 3 | 包括绘制脸部轮廓, 提取图片人脸, 4 | 5 | 人脸美妆 6 | 7 | ![Aaron Swartz](https://github.com/RenDong3/OpenCV_Notes/raw/master/face_recognition/images/33.jpg) 8 | -------------------------------------------------------------------------------- /video2img/Readme: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /video2img/avi2img.py: -------------------------------------------------------------------------------- 1 | #-*- coding: utf-8 -*- 2 | import os 3 | import cv2 4 | 5 | 6 | video_path = '/home/ren_dong/PycharmProjects/OpenCv/blog/video/1.avi' 7 | save_path = '/home/ren_dong/PycharmProjects/OpenCv/blog/img/' 8 | 9 | try: 10 | if not os.path.exists(save_path): 11 | os.mkdir(save_path) 12 | except: 13 | print('path is exist') 14 | 15 | 16 | def video2img(video_path, save_path): 17 | 18 | cap = cv2.VideoCapture(video_path) 19 | isopened = cap.isOpened() 20 | 21 | i = 1 22 | if cap.isOpened(): 23 | flag, frame = cap.read() 24 | 25 | else: 26 | flag = False 27 | print('video is not open..') 28 | 29 | 30 | while(flag): 31 | 32 | flag, frame = cap.read() 33 | cv2.imwrite(save_path + str(i) + '.jpg', frame) 34 | i += 1 35 | 36 | 37 | cap.release() 38 | if __name__ == '__main__': 39 | 40 | video2img(video_path, save_path) 41 | -------------------------------------------------------------------------------- /video2img/img2avi.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | 4 | 5 | def img2avi(): 6 | 7 | file_path = '/home/ren_dong/PycharmProjects/OpenCv/blog/imgs' 8 | save_path = file_path + '/' + '%s.avi' % str('result') 9 | 10 | file_list = os.listdir(file_path) 11 | #视频的帧速率,秒为单位,一秒播放多少张图片 12 | fps = 2 13 | img = cv2.imread('/home/ren_dong/PycharmProjects/OpenCv/blog/imgs/000001.jpg') 14 | size = (img.shape[1],img.shape[0]) 15 | #size视频图片的尺寸 16 | fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G') 17 | videoWriter = cv2.VideoWriter(save_path, fourcc, float(fps), size) 18 | #cv2.VideoWriter(1,2,3,4) 19 | #参数1 文件名称 参数2:选择编译器 参数3:设置帧率 参数4:设置视频尺寸 20 | 21 | 22 | for item in file_list: 23 | if item.endswith('.jpg'): 24 | item = file_path + '/' + item 25 | img = cv2.imread(item) 26 | img = cv2.resize(img, size) 27 | videoWriter.write(img) 28 | 29 | 30 | videoWriter.release() 31 | cv2.destroyAllWindows() 32 | 33 | 34 | if __name__ == '__main__': 35 | img2avi() 36 | 37 | 38 | 39 | 40 | --------------------------------------------------------------------------------