使用OpenCV测量两个元素之间的距离

5

我有一段从汽车上拍摄的视频。我的程序正在测量前轮和路上白线之间的距离。这个脚本对于左侧视频和右侧视频都运行得很好。

但是有时它会在右边的视频中测量前轮与白线之间的错误距离。

thresh = 150
distance_of_wood_plank = 80
pixel_of_wood_plank = 150
origin_width = 0
origin_height = 0
wheel_x = 0; wheel_y = 0 #xpoint and ypoint of wheel

df = pandas.DataFrame(columns=["Frame_No", "Distance", "TimeStrap"])
cap = cv2.VideoCapture(args.video)
frame_count = 0;
while(cap.isOpened()): #Reading input video by VideoCapture of Opencv
    try:
        frame_count += 1
        ret, source = cap.read() # get frame from video
        origin_height, origin_width, channels = source.shape

        timestamps = [cap.get(cv2.CAP_PROP_POS_MSEC)]
        milisecond = int(timestamps[0]) / 1000
        current_time = str(datetime.timedelta(seconds = milisecond))
        cv2.waitKey(1)
        grayImage = cv2.cvtColor(source, cv2.COLOR_RGB2GRAY) # get gray image
        crop_y = int(origin_height / 3 * 2) - 30
        crop_img = grayImage[crop_y:crop_y + 100, 0:0 + origin_width] # get interest area
        blur_image = cv2.blur(crop_img,(3,3))
        ret, th_wheel = cv2.threshold(blur_image, 10, 255, cv2.THRESH_BINARY) #get only wheel
        ret, th_line = cv2.threshold(blur_image, 150, 255, cv2.THRESH_BINARY) #get only white line
        contours, hierarchy = cv2.findContours(th_wheel, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2:]
        # get xpoint and ypoint of wheel
        for cnt in contours:
            x, y, w, h = cv2.boundingRect(cnt)
            if (x < origin_width/ 4):
                continue
            elif (w < 10):
                continue
            elif (w > 80):
                continue
            elif (x > origin_width / 4 * 3):
                continue
            wheel_x = int(x)
            wheel_y = int(y + h / 2 - 8)
        pixel_count = 0 # count of pixel between wheel and white line
        # get distance between wheel and white line
        if (wheel_x > origin_width/2):
            wheel_x -= 7
            for i in range(wheel_x, 0, -1):
                pixel_count += 1
                suit_point = th_line[wheel_y,i]
                if (suit_point == 255):
                    break
                if (i == 1):
                    pixel_count = 0
            pixel_count -= 4
            cv2.line(source, (wheel_x - pixel_count, wheel_y + crop_y), (wheel_x, wheel_y + crop_y), (255, 0, 0), 2)
        else :
            wheel_x += 7
            for i in range(wheel_x , origin_width):
                pixel_count += 1
                suit_point = th_line[wheel_y,i]
                if (suit_point == 255):
                    break
                if (i == origin_width - 1):
                    pixel_count = 0
            pixel_count += 4
            cv2.line(source, (wheel_x, wheel_y + crop_y), (wheel_x + pixel_count, wheel_y + crop_y), (255, 0, 0), 2)
        distance_Cm = int(pixel_count * 80 / pixel_of_wood_plank)
        str_distance = ""
        if distance_Cm > 10:
            str_distance = str(distance_Cm) + "Cm"
        else:
            str_distance = "No white line"

        cv2.putText(source, str_distance, (50, 250), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2, cv2.LINE_AA)

        df = df.append({'Frame_No': frame_count,'Distance': str_distance ,'TimeStrap': current_time}, ignore_index = True)

        df.to_csv("result.csv")
        cv2.imshow("Distance_window", source)
        cv2.waitKey(1)
    except:
        pass

以下是视频链接:https://drive.google.com/file/d/1IjJ-FA2LTGv8Cz-ReL7fFI7HPTiEhyxF/view?usp=sharing

(备注:此视频与IT技术有关)

1个回答

6
你在测量轮胎和白线之间的距离方面做得非常好。你需要考虑的是样本中有多少噪音。除非你停下卡车,走出去用卷尺测量轮胎到白线的距离,否则你永远不会真正知道它有多远。此外,你还需要考虑,除非你撞毁卡车,否则轮胎到白线的距离不会在每个帧之间变化超过几个像素。
最佳解决方案是卡尔曼滤波器,但它相当复杂。我使用了一个更简单的解决方案。为了找到线的位置,我平均了最后四个值以减小噪声。 average
import numpy as np, cv2

thresh = 150
distance_of_wood_plank = 80
pixel_of_wood_plank = 150
origin_width = 0
origin_height = 0
wheel_x = 0; wheel_y = 0 #xpoint and ypoint of wheel

cap = cv2.VideoCapture('/home/stephen/Desktop/20180301 1100 VW Right.mp4')
frame_count = 0;
vid_writer = cv2.VideoWriter('/home/stephen/Desktop/writer.avi', cv2.VideoWriter_fourcc('M','J','P','G'), 30, (480,360))

positions = []

import math
def distance(a,b): return math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)

while(cap.isOpened()): #Reading input video by VideoCapture of Opencv
    frame_count += 1
    ret, source = cap.read() # get frame from video
    origin_height, origin_width, channels = source.shape
    grayImage = cv2.cvtColor(source, cv2.COLOR_RGB2GRAY) # get gray image
    crop_y = int(origin_height / 3 * 2) - 30
    crop_img = grayImage[crop_y:crop_y + 100, 0:0 + origin_width] # get interest area
    blur_image = cv2.blur(crop_img,(3,3))
    ret, th_wheel = cv2.threshold(blur_image, 10, 255, cv2.THRESH_BINARY) #get only wheel
    ret, th_line = cv2.threshold(blur_image, 150, 255, cv2.THRESH_BINARY) #get only white line
    contours, hierarchy = cv2.findContours(th_wheel, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2:]
    # get xpoint and ypoint of wheel
    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        if (x < origin_width/ 4):
            continue
        elif (w < 10):
            continue
        elif (w > 80):
            continue
        elif (x > origin_width / 4 * 3):
            continue
        wheel_x = int(x)
        wheel_y = int(y + h / 2 - 8)
    pixel_count = 0 # count of pixel between wheel and white line
    # get distance between wheel and white line
    if (wheel_x > origin_width/2):
        wheel_x -= 7
        for i in range(wheel_x, 0, -1):
            pixel_count += 1
            suit_point = th_line[wheel_y,i]
            if (suit_point == 255):
                break
            if (i == 1):
                pixel_count = 0
        pixel_count -= 4
    else :
        wheel_x += 7
        for i in range(wheel_x , origin_width):
            pixel_count += 1
            suit_point = th_line[wheel_y,i]
            if (suit_point == 255):
                break
            if (i == origin_width - 1):
                pixel_count = 0
        pixel_count += 4
        a,b = (wheel_x - pixel_count, wheel_y + crop_y), (wheel_x, wheel_y + crop_y)
        if distance(a,b)>10: positions.append((wheel_x + pixel_count, wheel_y + crop_y))

    if len(positions)>10:
        radius = 2
        for position in positions[-10:]:
            radius += 2
            center = tuple(np.array(position, int))
            color = 255,255,0
            cv2.circle(source, center, radius, color, -1)
        x,y = zip(*positions[-4:])
        xa, ya = np.average(x), np.average(y)
        center = int(xa), int(ya)
        cv2.circle(source, center, 20, (0,0,255), 10)

    cv2.imshow("Distance_window", source)
    vid_writer.write(cv2.resize(source, (480,360)))
    k = cv2.waitKey(1)
    if k == 27: break

cv2.destroyAllWindows()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接