当前位置:   article > 正文

基于OpenCV 在python中实现图像自动检测+手动截图_python opencv 屏幕找图

python opencv 屏幕找图


前言

提示:这里可以添加本文要记录的大概内容:

针对图像检测技术的发展,自动化的需求,因此本文开发了一种基于OpenCV图像检测及图像分割技术。


提示:以下是本篇文章正文内容,下面案例可供参考

一、设计流程

请添加图片描述

1.1图片读取

在这里插入图片描述

1.2 图片处理

在这里插入图片描述

1.3 图片裁剪及识别

在这里插入图片描述

二、图像检测部分

# 检测红色的阈值
def detect(path_input,path_save):
    '''
    param:
    path_input = 输入图片路径
    path_save = 保存路径
    function:
    处理图片,对图片进行灰度,滤波,二值化,腐蚀膨胀等处理,并裁剪后保存
    '''
    global img , img_name
    img_name = path_save
    img = cv2.imread(path_input)
    img=cv2.resize(img,(img.shape[1]//4,img.shape[0]//4))
    cv2.namedWindow('photo',0)              # 打开待截图窗口 ,此窗口可以对图片操作
    cv2.resizeWindow("photo", img.shape[1], img.shape[0])
    cv2.imshow('photo', img)
    cv2.setMouseCallback('photo', on_mouse) # 回调函数
    # 防止图片分辨率太大,最后保存失败,因此重置分辨率,通常横拍的图片会失败
    
    
    
    
    lower_blue=np.array([0,20,170])
    upper_blue=np.array([15,200,255])
    
    # change to hsv model
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    
    
    
    # get mask
    mask = cv2.inRange(hsv, lower_blue, upper_blue)
    
    # detect blue
    image = cv2.bitwise_and(img, img, mask=mask)
    #cv2.imshow('detect',image)
    
    # 滤波
    image = cv2.blur(image, (9,9))
    #cv2.imshow('blur',image)
    
    
    # 灰度
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    '''
    gradX = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)
    gradY = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=-1)
    cv2.imshow('',gray)
    cv2.imshow('1',gradX)
    cv2.imshow('2',gradY)
    
    
    
    
    # subtract the y-gradient from the x-gradient
    # 图片加减法
    
    gradient = cv2.subtract(gradX, gradY)
    cv2.imshow('subtract',gradient)
    '''
    #dst1 = cv2.add(gradX, gradY)
    #cv2.imshow('add',dst1)
    
    # 转换数据为uint8 
    gradient = cv2.convertScaleAbs(gray)
    #cv2.imshow('gray',gray)
    
    '''
    # blur and threshold the image
    # 均值滤波 高斯
    blurred = cv2.blur(gradient, (3,3))
    cv2.imshow('blur',blurred)
    
    blurred=cv2.GaussianBlur(gradient,(5,5),0,0)
    cv2.imshow('GaussianBlur',blurred)
    '''
    
    
    # 二值化
    (_, thresh) = cv2.threshold(gradient,70, 255, cv2.THRESH_BINARY)
    #cv2.imshow('threshold',thresh)
    closed = thresh.copy()
    
    # 产生卷积核
    
    '''
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15,15))
    # 形态滤波
    closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
    cv2.imshow('CLOSE',closed)
    '''
    '''
    closed = cv2.morphologyEx(thresh, cv2.MORPH_TOPHAT, kernel)
    cv2.imshow('TOPHAT',closed)
    
    closed = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
    closed_2 = cv2.morphologyEx(thresh, cv2.MORPH_GRADIENT, kernel)
    closed_4 = cv2.morphologyEx(thresh, cv2.MORPH_BLACKHAT, kernel)
    cv2.imshow('OPEN',closed)
    cv2.imshow('_GRADIENT',closed_2)
    cv2.imshow('BLACKHAT',closed_4)
    
    '''
    
    # perform a series of erosions and dilations
    #形态学腐蚀与膨胀
    closed = cv2.erode(closed, (1,1), iterations=3)
    #cv2.imshow('erode',closed)
    
    closed = cv2.dilate(closed,(3,3), iterations=9)
    #cv2.imshow('dilate',closed)
    
    
    (cnts, a) = cv2.findContours(closed.copy(), cv2.RETR_LIST,
                                 cv2.CHAIN_APPROX_SIMPLE)
    #c = sorted(cnts, key=cv2.contourArea, reverse=True)[0]
    
    c = max(cnts, key=cv2.contourArea)
    # compute the rotated bounding box of the largest contour
    rect = cv2.minAreaRect(c)
    
    box = np.int0(cv2.boxPoints(rect)) # 矩形的四个点
     
    # draw a bounding box arounded the detected barcode and display the image
    cv2.drawContours(image, [box], -1, (0, 255, 0), 3)
    #cv2.imshow("Image", image)
    cv2.imwrite('draw.jpg',image)
    #cv2.waitKey(0)
    Xs = np.array([i[0] for i in box])
    Ys = np.array([i[1] for i in box])
    # 将矩形整形到 图片尺寸中,防止超边
    Xs[Xs < 0] = 0
    Xs[Xs > img.shape[1]] = img.shape[1]
    Ys[Ys < 0] = 0
    Ys[Ys > img.shape[0]] = img.shape[0]
    
    x1 = min(Xs)
    x2 = max(Xs)
    y1 = min(Ys)
    y2 = max(Ys)
    cropImg = img[y1:y2, x1:x2]
    
    cv2.imwrite(path_save, cropImg) # 保存
    cv2.imshow('AOTUcut',cropImg)


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 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
  • 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
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146

文中相关参数可以实验性地更改,比如滤波值,腐蚀膨胀参数等。
这里需要所检测物体的hsv颜色阈值,hsv的阈值检测程序如下。

import cv2
import numpy as np
#   读 取 图 片
img = cv2.imread('38.jpg')  # 直接读为灰度图像

height, width = img.shape[:2]
size = (int(width //4), int(height //4))  # 缩小或者放大图片显示大小
img = cv2.resize(img, size, interpolation=cv2.INTER_AREA)
#BGR转化为HSV
HSV=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
#鼠标点击响应事件


# 当鼠标按下时变为True
drawing=False
ix,iy=-1,-1

def draw_circle(event,x,y,flags,param):
    global ix,iy,drawing
    # 当按下左键是返回起始位置坐标
    if event==cv2.EVENT_LBUTTONDOWN:
        drawing=True
        ix,iy=x,y
    # 当鼠标左键按下并移动是绘制图形。event 可以查看移动,flag 查看是否按下
    elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
        if drawing==True:
            cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
    # 当鼠标松开 停止绘画
    elif event==cv2.EVENT_LBUTTONUP:
        drawing==False





def getposHsv(event,x,y,flags,param):
    if event==cv2.EVENT_LBUTTONDOWN:
        print("HSV is",HSV[y,x],type(HSV),HSV[y,x][0],HSV[y,x][1],HSV[y,x][2])
        param = param.append([HSV[y,x][0], HSV[y,x][1], HSV[y,x][2]])
        

def getposBgr(event,x,y,flags,param):
    if event==cv2.EVENT_LBUTTONDOWN:
        print("Bgr is",img[y,x])

h=[]

cv2.imshow("imageHSV",HSV)
cv2.imshow('image',img)
#cv2.setMouseCallback("imageHSV",getposHsv,param =h)
#cv2.setMouseCallback("image",getposBgr)
cv2.setMouseCallback("cut",draw_circle)
cv2.waitKey(0)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 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
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

将待测图片加载后运行程序即可。

三、鼠标截图功能

def on_mouse(event, x, y, flags, param):
    global point1, point2
    img2 = img.copy()
    if event == cv2.EVENT_LBUTTONDOWN:                                      # 左键点击时
        point1 = (x,y)                                                      # 记录第一个点
        cv2.circle(img2, point1, 10, (0,255,0), 3)                          # 第一个点画园 图像,圆心,半径
        cv2.imshow('photo', img2)                                           # 展示画园时的画面
    elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON): # 按住左键拖曳 当鼠标左键按住时
        cv2.rectangle(img2, point1, (x,y), (255,0,0), 3)                    # 画矩形
        cv2.imshow('photo', img2)                                           # 展示画矩形时的画面
    elif event == cv2.EVENT_LBUTTONUP:                                      # 左键释放 当鼠标左键松开时
        point2 = (x,y)                                                      # 记录第二个点
        cv2.rectangle(img2, point1, point2, (0,0,255), 3)                   # 画框 变色
        cv2.imshow('photo', img2)                                           # 展示
        min_x = min(point1[0],point2[0])                                    # 赋值
        min_y = min(point1[1],point2[1])
        width = abs(point1[0] - point2[0])
        height = abs(point1[1] -point2[1])
        cut_img = img[min_y:min_y+height, min_x:min_x+width]
        cv2.imwrite(img_name, cut_img)
        cv2.imshow('HAND cut',cut_img)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

四、主函数

if __name__ == '__main__':
    path = r'photos'                                     # 读取位置
    save = r'save'                                       # 保存位置
    # 遍历文件
    num = 0
    for file in os.listdir(path):
        path_img = os.path.join(path,file)              # 读取路径
        save_img = os.path.join(save,file)              # 保存路径
        if not os.path.exists('{}/{}.jpg'.format(path,num)): # 如果文件不存在 则重新命名
             os.rename(path_img, '{}/{}.jpg'.format(path,num))
             print('',path_img, '更名为:' , '{}/{}.jpg'.format(path,num))
             detect(path_input='{}/{}.jpg'.format(path,num),path_save='{}/{}.jpg'.format(save,num))
             cv2.waitKey(0)
             cv2.destroyAllWindows()
        else:
            print(path_img)
            detect(path_input=path_img,path_save=save_img)
            cv2.waitKey(0) 
            cv2.destroyAllWindows()
        num+=1
        
        
    
    print('-----------------全部处理完毕---------------------\n')
    print('总计 %s 张'%num)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

对path路径里的图片进行遍历读取,并自动识别后裁剪,保存到save文件夹中。

五、结果展示

5.1 原图

在这里插入图片描述

5.2 图片hsv阈值筛选

在这里插入图片描述

5.3 滤波

在这里插入图片描述

5.4 灰度

在这里插入图片描述

5.5 阈值化(二值化)

在这里插入图片描述

5.6 腐蚀

在这里插入图片描述

5.7 膨胀

在这里插入图片描述

5.8 边缘检测结果

在这里插入图片描述

5.9 最终结果

在这里插入图片描述

5.10 视频演示

暂无,待上传

六、总结

本次批量处理的检测合格率为45/72,针对不合格的也作出了针对性补偿,如避免遮挡,保持间隔等。并开发了手动截图的功能,以此保证本项目功能的全面实现。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/86674
推荐阅读
相关标签
  

闽ICP备14008679号