Environment: Python 3.7 OpenCV3.4.3.18
Tools:
opencv_annotation.exe
opencv_createsamples.exe
opencv_traincascade.exe
Environment and tools download and installation
Terminal command of OpenCV Library under cmd
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-contrib-python==3.4.3.18
It includes the main modules of OpenCV and opencv contribution library
Tools can be downloaded from GitHub
https://github.com/opencv/opencv/releases?after=3.4.3
Install OpenCV in the following directory
1, Preparation stage
File template
positive_images to place positive sample images and negative_image places the negative sample image and xml as the trained classifier file
Sample collection
Positive sample: the sample corresponding to the category we want to correctly classify. For example, if we want to classify a picture to determine whether it belongs to pineapple, the picture of pineapple will be a positive sample during training.
Negative sample: either the sample corresponding to the classification we want, or the picture of pineapple
The more sample data, the better the detection effect, the more obvious the characteristics of positive samples, and the more complex the background of negative samples.
1. Go to www.kaggle.com to download the data set you want, or use scratch + selenium to crawl pictures in batches
2. Take pictures of the object you want to detect
2, Pretreatment
Image water injection processing: automatically rotate, translate and zoom the image to increase the number of samples
For example, by rotating
"path Is the picture path. After execution, 11 pictures rotated by 30 degrees will be generated in the same directory" def spin(path): retval=cv2.imread(path) he,we=retval.shape[:2] for x in range(1,12): M=cv2.getRotationMatrix2D(center=(we/2,he/2),angle=x*30,scale=1) M=cv2.warpAffine(retval,M,(we,he)) new_path=path[:-3]+'-spin'+str(x)+'.jpg' #print(new_path) cv2.imwrite(new_path,M)
Adjust brightness:
"path Is the picture path. After execution, five pictures with increasing brightness will be generated in the same directory" def light(path): retval=cv2.imread(path) img_hsv = cv2.cvtColor(retval, cv2.COLOR_BGR2HSV) darker_hsv = img_hsv.copy() for y in range(1,6): darker_hsv[:, :, 2] = darker_hsv2[:, :, 2]+2*y darker_img = cv2.cvtColor(darker_hsv, cv2.COLOR_HSV2BGR) new_path=path[:-3]+'-light+'+str(x)+'ipg' cv2.imwrite(new_path, darker_img)
Unified image size processing (40 * 40):
Batch rename picture files in folders
import os from PIL import Image class BatchRename(): def __init__(self): self.path = r'.\positive_images' def rename(self): filelist = os.listdir(self.path) total_num = len(filelist) i = 0 for item in filelist: if item.endswith('.jpg'): src = os.path.join(os.path.abspath(self.path), item) print(src) dst = os.path.join(os.path.abspath(self.path), str(i) + '.jpg') try: os.rename(src, dst) print ('converting %s to %s ...' % (src, dst)) i = i + 1 except : continue print ('total %d to rename & converted %d jpgs' % (total_num, i)) if __name__ == '__main__': demo = BatchRename() demo.rename() pass
After execution
Batch modify picture size
from PIL import Image import os.path import glob def convertjpg(jpgfile,outdir,width=40,height=40): img=Image.open(jpgfile) try: new_img=img.resize((width,height),Image.BILINEAR) new_img.save(os.path.join(outdir,os.path.basename(jpgfile))) except Exception as e: print(e) for jpgfile in glob.glob(r".\positive_images\*.jpg"): #The modified pixels are stored in the images file convertjpg(jpgfile,r".\positive_images")
3, Generate sample description file
To generate a positive sample description file, you can use the annotation tool opencv_annotation.exe
opencv_ For the use of annotation.exe, enter opencv under cmd in the current directory_ Annotation.exe can see the instructions
For example: opencv_annotation.exe - a = generated pos.txt path - i = positive sample folder path
Mark with the left mouse button and select the object to be recognized in a rectangular box
In English, 'c' is the confirmation box,'d 'deletes the selected box,' n 'is the next one,' esc 'is the stop.
If there is only one object in the picture, you can directly generate a description file (try to label it with opencv_annotation, the effect is better)
file_dir=os.getcwd() print(file_dir) file_dir=r'.\positive_images' L=[] i=0 with open(r".\pos.txt","w+") as f: for root, dirs, files in os.walk(file_dir): for file in files: if os.path.splitext(file)[1] == '.jpg': L.append(os.path.join(root, file)) f.write(L[i]+' 1'+' 0'+' 0'+' 40'+' 40'+'\n') i+=1
Generate pos.txt
Generate negative sample description file (without annotation)
file_dir=r'.\negative_image' L=[] i=0 with open(r".\neg.txt","w+") as f: for root, dirs, files in os.walk(file_dir): for file in files: if os.path.splitext(file)[1] == '.jpg': L.append(os.path.join(root, file)) f.write(L[i]+'\n') i+=1 print("ok")
Generate neg.txt
4, Composite sample vec file
Here, you only need to synthesize the vec file of positive samples, but not negative samples. Opencv is used here_ createsamples.exe
opencv_ For the use of createsamples.exe, enter opencv under cmd in the current directory_ Createsamples.exe can see the instructions
For example, opencv_createsamples.exe -vec pos.vec - info pos.txt -num 50 -w 40 -h 40
-The vec parameter represents the storage location of the. vec file;
-info represents the location of the generated annotation;
-num number of positive samples generated
-w width of the window- h window height;
After that, the pos.vec file is generated in the current directory
5, Training model
The training model uses opencv_traincascade.exe
opencv_ For the use of traincascade.exe, enter opencv under cmd in the current directory_ Traincascade.exe can see the instructions for use
For example: opencv_traincascade.exe -data xml -vec pos.vec -bg neg.txt -numPos 10 -numNeg 2000 -numStages 15 -w 40 -h 40 -minHitRate 0.999 -maxFalseAlarmRate 0.5 -mode ALL
-data: specify the folder to save the training results;
-vec: specify positive sample set;
-bg: specify the description folder of negative samples;
-numPos: specify the number of positive samples participating in training at each level (less than the total number of positive samples);
-numNeg: specify the number of negative samples participating in training at each level (which can be greater than the total number of negative sample pictures);
-numStage: training level;
-w: Width of positive sample- h: The height of positive samples; (must be consistent with the - W and - H values used in opencv_createsample)
-minHitRate: the hit rate required for each level (generally 0.95-0.995);
-Maxfalse alarmrate: the maximum error detection rate allowed for each level;
-mode: used when Haar like feature is used. BASIC, CORE or ALL are optional; (ALL uses vertical and 45 degree rotation features.)
(this screenshot is the result of running opencv_traincascade.exe again after training the model)
The trained classifier files are in the xml folder
6, Test model
import numpy as np import cv2 #Load cascader pineapple_cascade = cv2.CascadeClassifier(r'xml\cascade.xml') #testing def detect(image): #Convert image to grayscale image gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #Call cascader pineapples = face_cascade.detectMultiScale(gray, scaleFactor=1.15, minNeighbors=5, minSize=(10, 10)) print(pineapples) print("find{0}A pineapple!".format(len(pineapples))) #Draw the pineapple area for (x, y, w, h) in pineapples: cv2.circle(image, (int((x + x + w) / 2), int((y + y + h) / 2)), int(w / 2), (0, 255, 0), 2) return image retval=cv2.imread(r'test.jpg') image=detect(retval) cv2.imwrite('detect.jpg',image)
After running, the detected image detect.jpg is generated (this is just a demonstration, there are few samples, and the effect is not very good)
The above is just a simple training step display for reference and learning