차선 인식 프로젝트 과정

happy_quokka·2023년 10월 30일
0

자율주행 프로젝트

목록 보기
1/15

이진화

gray scale

gray_eqaulize

  • avg_time: 0.980676ms

50





55




60

gray_stretch

  • avg_time: 2.85232

130





140

150




160





HLS (L부분)

equalize

  • avg_time: 0.96142

50



60



65





65 + morphology

  • erode 1 : 큰 노이즈는 안사라짐 + 차선이 조금 얇아짐

  • erode 2 : 노이즈가 많이 사라졌지만 차선이 많이 얇아져서 끊기는 부분이 생김

  • open 1 : 큰 노이즈는 살아있다 + 차선이 조금 끊기는 느낌이...

  • open 2 : 큰 노이즈는 없어졌지만 기존의 얇았던 차선은 사라진다.



  • open 1 + close 1

Note
The number of iterations is the number of times erosion or dilatation operation will be applied. For instance, an opening operation (MORPH_OPEN) with two iterations is equivalent to apply successively: erode -> erode -> dilate -> dilate (and not erode -> dilate -> erode -> dilate).

70




stretch

  • avg_time: 2.79228 / minmax 제외 avg_time: 1.93319

120





130







150






160



170




이진화 수행속도

  • adaptive :8 ~ 9ms
  • simple : 0.6 ~ 0.7ms

라이다 mask

  • 이진화 수행 후 가우시안 블러링 하기 전에 적용

  • 가우시안 블러링 이후에 수행하면 블러 때문에 캐니에지에서 에지로 검출된다

캐니 에지

  • 모폴로지 연산 결과와 가우시안 블러 결과의 차이가 별로 없는데 가우시간 블러가 조금 더 깔끔하다.

허프 변환

  • threshold 60과 100

차선 검출

왼, 오른 차선 구분

  • 아래와 같이 하는 경우 중심을 넘어가서 차선 검출이 안된다.
if((slope < 0) && (x2 < frame.cols / 2))
else if((slope > 0) && (x1 > frame.cols /2))

  • 이렇게 변경하면 검출된다.
if((slope < 0) && (x1 < frame.cols / 2))
else if((slope > 0) && (x2 > frame.cols /2))

  • 또한 왼쪽(음수), 오른쪽(양수) 기울기와 좌표에 따라 line을 선택한다. 그럼 아래와 같은 차선이 아닌 경우가 제거된다







  • 또한 기울기를 아래와 같이 변경하면 기울기가 0에 가까운 직선도 제거된다
if((slope < -0.1) && (x1 < frame.cols / 2))
else if((slope > 0.1) && (x2 > frame.cols /2))


문제

문제 1 : 검출되어야하는 차선이 검출이 안된다.




문제 2 : 정지선 검출이 안된다

  • 이건 나중에 중앙에서 기울기가 0에 가깝다면, 이라는 경우로 검출할 수 있을지도?


  • 이거는...전반적인 분포에서 많이 벗어나면 제거?
  • 가장 문제인 부분 3개



차선 좌표 출력

  • 차선이 없는 경우 0, 640으로 고정
  • 차선이 끊기는 경우가 해결안된다...

차선 끊김 해결

기울기 대칭

  • 직진일 경우 한 차선이라도 검출된다면 대칭으로 기울기, 절편 만들어서 사용
  • 직진인 경우는 나름 추정을 잘한다.

  • 차선 예측 후 범위가 넘어가는 경우 발생. 이 경우는 예측하고 나서 범위가 영상 밖이라면 0, 640으로 지정하는 코드 추가
if((lpos >= 0) && (k_under_limit < abs(left_slope)) && (abs(left_slope) < k_upper_limit)){
            rpos = lpos + k_lane_width;
            if(rpos > k_lane_width) rpos = k_frame_width;
            right_slope = -left_slope;
            right_intercept = k_offset - right_slope * rpos;   
        }

-그랬더니...이렇게 이상하게 예측...

  • 그 이유는 맞게 검출된 rpos지만 영상을 벗어낫기에 640으로 조정한거여서 조정하기 전의 Rpos로 기울기, 절편을 수정한 후 변경해야한다.
if((lpos >= 0) && (k_under_limit < abs(left_slope)) && (abs(left_slope) < k_upper_limit)){
            rpos = lpos + k_lane_width;
            right_slope = -left_slope;
            right_intercept = k_offset - right_slope * rpos;
            if(rpos > k_lane_width) rpos = k_frame_width;
        }

  • 완벽하지는 않지만 아까보다 나아졌다.
  • 곡선일 때는 추정이 너무 복잡해서 구현하지 못했다. 다른 방법이 필요할듯

칼만 필터 사용

  • 곡선, 직선 검출이 가능하지만 전반적으로 튀는 값들이 많다ㅠㅠ





문제

  • 직선을 추정하고 offset인 400에서의 x좌표를 찾다보니 영상을 벗어나서 계산 되는 경우가 있다.
    • 이는 0보다 작고 640보다 큰 경우는 0, 640으로 지정해주는 코드 추가로 해결
  • 그러다보니 차선의 끊김이 아니라 가려진 경우에도 차선 추정을 하게 되어 조금 부정확해지는 경우가 있다
    • 이는 왼, 오른쪽 차선의 lines를 배열로 따로 저장한 수 그 개수가 0이면 끊김이고 그렇지 않으면 값이 640으로 존재하는 것이라고 구분해야할 것 같다.
    • 아니다. 그냥 그 if문의 순서를 바꾸면 될지도? 지금은 if로 기울기와 절편이 0인 경우 640을 지정하였다. 그 후 640인 경우는 끊겼다고 판단하여 추가작업을 진행하였는데 640을 지정하지 않으면 해결될 문제 인것 같다.
    • 해결!!! : 아래와 같이 끊긴 경우는 아에 영상 밖에 존재하도록 설정하고 이를 통해 끊김확인 후 추정을 진행하였다.
void calculatePos(const double& slope, const double& intercept, int32_t& pos, bool left = false, bool right = false)
{
    if(cvRound(slope) == 0 && cvRound(intercept) == 0){
        if (left)
            pos = -1;
        else if (right)
            pos = frame_width << 1;
    }
    else{
        pos = static_cast<int32_t>((offset - intercept)/ slope);
        if (left){
            if (pos < 0) pos = 0;
        }
        if (right){
            if(pos > frame_width) pos = frame_width;
        }
    }
}

void estimatePos(double& left_slope, double& left_intercept, double& right_slope, double& right_intercept, int32_t& lpos, int32_t& rpos)
{
    if((lpos < 0) && (rpos <= frame_width)){
        if((0.6 < abs(right_slope)) && (abs(right_slope) < 1)){
            lpos = rpos - lane_width;
            left_slope = -right_slope;
            left_intercept = offset - left_slope * lpos;
        }
    }
    else if((rpos > frame_width) && (lpos >= 0)){
        if((0.6 < abs(left_slope)) && (abs(left_slope) < 1)){
            rpos = lpos + lane_width;
            right_slope = -left_slope;
            right_intercept = offset - right_slope * rpos;
        }
    }
}
  • 이전 프레임의 기울기를 활용하는 부분이 있었는데 현재 프레임에 가중치를 높게 두었다. 하지만 현재의 값이 0인 경우 값이 이상하게 계산되어 일단 주석처리.

추가 사항

  • 실제 자이카 할때는 밝기값이 다를테니 밝기를 128로 맞춘후 threshold 적용하면 좋겠다.

정지선 검출

try1

  • 프레임 너비의 1/4 ~ 3/4 사이에 x 좌표 존재 && abs(기울기) < 0.15(threshold)이고 그 개수가 2개 이상이면 정지선!!
else if((abs(slope) <= 0.15) && (x1 > k_frame_width/4) && (x1 < k_frame_width/4 * 3))
            stop_lines.emplace_back(x1,y1,x2,y2);
  • 차선이 아닌 부분도 정지선으로 인식된다..
  • 정지선은 이렇게!

try 2 : x2로 끝 좌표 비교

else if((abs(slope) <= 0.15) && (x1 > k_frame_width/4) && (x2 < k_frame_width/4 * 3))
            stop_lines.emplace_back(x1,y1,x2,y2);

try 3 : threshold width 변경 -> 선택

else if((abs(slope) <= 0.15) && (x1 > k_frame_width/5) && (x2 < k_frame_width/5 * 4))
            stop_lines.emplace_back(x1,y1,x2,y2);
  • 이 조건을 만족하는 직선이 2개 이상일 때 정지선!


차선 중앙과 프레임 중앙 차이 = error

  • 차선 너비의 중앙과 lpos, rpos의 중앙을 통해 후에 조향 조절

0개의 댓글