2022-06-14 Python OpenCV 常用工具类

2022-06-14  本文已影响0人  颈椎以上瘫痪

显示图像

cv.imshow()是显示图像的函数,需要2个参数,一个是需要显示的图像,还一个是显示图像窗口的标题,在一个进程中同样标题的窗口只能存在一个,比如你先显示一个标题1的图像,再显示一个标题1的图像,那么后显示的图像窗口就会将前面那个销毁掉。这个函数显示图像窗口是OpenCV的调试窗口,默认是不能缩放的,图像有多大,窗口就显示多大,但是在过程中我们往往会显示很多窗口,也需要手动缩放和拖动这些窗口,所以在定义这个窗口时需要执行一个cv.WINDOW_NORMAL属性,然后在这个窗口里面显示图像就可以缩放了。

# 显示图像
def show(title, image):
    cv.namedWindow(title, cv.WINDOW_NORMAL)
    cv.imshow(title, image)

绘制矩形

cv.rectangle()是在图像上绘制一个矩形的函数,需要的参数有一个图像,2个点(左上角和右下角),矩形框的颜色,矩形框的线宽。注意这里传入的坐标点的值不能是小数,如果你在计算过程中的数据精确到小数了,这里就需要采取一些手段来避免出错,比如这里对坐标值使用四舍五入。

def drawRectangle(canvas, p1, p2):
    cv.rectangle(canvas, (round(p1[0]), round(p1[1])), (round(p2[0]), round(p2[1])), (0, 0, 255), 2)

三角形已知三个角和1条边,求另2条边

三角形已知3个角度值和1条边长,可以使用这个函数计算另2条边长,注意数据的顺序,边长按照顺序其对角的顺序。

def calSide(angles, a):
    angleA = angles[0]
    angleB = angles[1]
    angleC = angles[2]

    b = math.sin(angleB / 180 * math.pi) * a
    c = math.cos(angleB / 180 * math.pi) * a
    return b, c

获取图像中某区域附近红色和绿色像素分量

def getRedAndGreenCount(img, point, offset, canvas):
    # 根据偏移量,在点附近绘制矩形
    cv.rectangle(canvas, (round(point[0] - offset), round(point[1] - offset)),
                 (round(point[0] + offset), round(point[1] + offset)), (0, 0, 255), 1)

    # 将这个矩形裁剪出来
    status = img[round(point[1] - offset):round(point[1] + offset), round(point[0] - offset):round(point[0] + offset)]
    if status is None:
        return None
    # show("RedAndGreen"+str(point),status)
    try:
        count = redAndGreen(status)
        return count
    except Exception:
        return None
    pass

判断图像中红色和绿色像素分量的数量

def redAndGreen(img):
    # 先将图像转成HSV
    hsvSrc = cv.cvtColor(img, cv.COLOR_BGR2HSV)
    # 找红色区间
    lowerColorRed = np.array([0, 43, 46])
    upperColorRed = np.array([10, 255, 255])
    hsvRed = cv.inRange(hsvSrc, lowerColorRed, upperColorRed)
    # 找绿色区间
    lowerColorGreen = np.array([35, 43, 46])
    upperColorGreen = np.array([77, 255, 255])
    hsvGreen = cv.inRange(hsvSrc, lowerColorGreen, upperColorGreen)

    # 找出各颜色图像中白色像素点的数量
    redCount = 0
    greenCount = 0
    w, h, c = img.shape
    for j in range(w):
        for k in range(h):
            if hsvRed[j, k] == (255.0):
                redCount = redCount + 1
            if hsvGreen[j, k] == (255.0):
                greenCount = greenCount + 1

    return greenCount + redCount

判断图像是红色还是绿色

def redOrGreen(img):
    # 先将图像转成HSV
    hsvSrc = cv.cvtColor(img, cv.COLOR_BGR2HSV)
    # 找红色区间
    lowerColorRed = np.array([0, 43, 46])
    upperColorRed = np.array([10, 255, 255])
    hsvRed = cv.inRange(hsvSrc, lowerColorRed, upperColorRed)
    # 找绿色区间
    lowerColorGreen = np.array([35, 43, 46])
    upperColorGreen = np.array([77, 255, 255])
    hsvGreen = cv.inRange(hsvSrc, lowerColorGreen, upperColorGreen)

    # 找出各颜色图像中白色像素点的数量
    redCount = 0
    greenCount = 0
    w, h, c = img.shape
    for j in range(w):
        for k in range(h):
            if hsvRed[j, k] == (255.0):
                redCount = redCount + 1
            if hsvGreen[j, k] == (255.0):
                greenCount = greenCount + 1

    if greenCount > redCount:
        return 1
    else:
        return 0

计算线段中点1到点2的方向

def calAngleLine(line):
    angle = 0
    point1 = (line[0], line[1])
    point2 = (line[2], line[3])
    x1, y1 = point1
    x2, y2 = point2

    # 水平
    if y1 == y2:
        # 右
        if x1 < x2:
            angle = 0
        # 左
        elif x1 > x2:
            angle = 180
        # 同一个点
        else:
            angle = 0
    # 向上
    elif y1 > y2:
        # 右上
        if x1 < x2:
            angle = 360 - calAngle(point1, point2, (x2, y1))[0]
        # 左上
        elif x1 > x2:
            angle = 180 + calAngle(point1, point2, (x2, y1))[0]
        # 上
        else:
            angle = 270
    # 向下
    else:
        # 右下
        if x1 < x2:
            angle = calAngle(point1, point2, (x2, y1))[0]
        # 左下
        elif x1 > x2:
            angle = 180 - calAngle(point1, point2, (x2, y1))[0]
        # 下
        else:
            angle = 90
    return angle

已知3个点求其三角形的角度

返回的数组中3个角度值,与传参进来的点的顺序是对应的。

def calAngle(p1, p2, p3):
    angles = []
    a = math.sqrt((p2[0] - p3[0]) * (p2[0] - p3[0]) + (p2[1] - p3[1]) * (p2[1] - p3[1]))
    b = math.sqrt((p1[0] - p3[0]) * (p1[0] - p3[0]) + (p1[1] - p3[1]) * (p1[1] - p3[1]))
    c = math.sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]))
    A = math.degrees(math.acos((a * a - b * b - c * c) / (-2 * b * c)))
    B = math.degrees(math.acos((b * b - a * a - c * c) / (-2 * a * c)))
    C = math.degrees(math.acos((c * c - a * a - b * b) / (-2 * a * b)))
    angles.append(A)
    angles.append(B)
    angles.append(C)
    return angles

角度校正

在使用角度时我们往往只需要0-360的值,但是角度在经过计算后经常会超过边界,所以使用这个函数可以将超出边界的值换算到边界内。

def rectifyAngle(angle):
    if angle >= 360:
        angle = angle - 360
    elif angle < 0:
        angle = angle + 360

    if angle < 0 | angle >= 360:
        return rectifyAngle(angle)

    return angle

计算点的偏移坐标

计算一个点的偏移坐标,需要一个点、一个角度、一个距离,计算出偏移后的点。

def calPoint4AngleDistance(center, angle, distance):
    x, y = center
    point = ()
    if angle >= 360:
        angle %= 360
    # 右
    if angle == 0:
        point = (x + distance, y)
        pass
    # 下
    elif angle == 90:
        point = (x, y + distance)
        pass
    # 左
    elif angle == 180:
        point = (x - distance, y)
        pass
    # 上
    elif angle == 270:
        point = (x, y - distance)
        pass
    # 右下
    elif angle > 0 and angle < 90:
        angles = []
        angles.append(90)
        angles.append(angle)
        angles.append(90 - angle)
        b, c = calSide(angles, distance)
        point = (x + c, y + b)
        pass
    # 左下
    elif angle > 90 and angle < 180:
        angles = []
        angles.append(90)
        angles.append(180 - angle)
        angles.append(angle - 90)
        b, c = calSide(angles, distance)
        point = (x - c, y + b)
        pass
    # 左上
    elif angle > 180 and angle < 270:
        angles = []
        angles.append(90)
        angles.append(angle - 180)
        angles.append(270 - angle)
        b, c = calSide(angles, distance)
        point = (x - c, y - b)
        pass
    # 右上
    elif angle > 270 and angle < 360:
        angles = []
        angles.append(90)
        angles.append(360 - angle)
        angles.append(angle - 270)
        b, c = calSide(angles, distance)
        point = (x + c, y - b)
        pass

    return point

求两点间距离

def getDistance(p1, p2):
    distance = math.pow((p1[0] - p1[0]), 2) + math.pow((p2[1] - p2[1]), 2)
    distance = math.sqrt(distance)
    return distance
上一篇下一篇

猜你喜欢

热点阅读