生活随笔
收集整理的這篇文章主要介紹了
车道线识别之——增强黄色车道线
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
為了更好的識(shí)別車(chē)道線,需要給黃色車(chē)道線增強(qiáng),方法是將RGB圖片轉(zhuǎn)換為HSV圖片,增強(qiáng)HSV圖片的第三位(V)的數(shù)值,再轉(zhuǎn)換成黑白圖片。這個(gè)方法只適用于白天并且車(chē)道線清晰的場(chǎng)景。
如下是普通代碼和CUDA代碼
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <cuda.h>
#include <cuda_runtime.h>using namespace std
;
using namespace cv
;void RGB_to_HSV(const cv
::Mat img_RGB
, cv
::Mat
&img_HSV
){int row
= img_RGB
.rows
;int col
= img_RGB
.cols
;int B
, G
, R
;int V
; int m
; int S
; int H
; for (int i
= 0; i
< row
; i
= i
+ 1) {for (int j
= 0; j
< col
; j
= j
+ 1) {B
= img_RGB
.at
<cv
::Vec3b
>(i
, j
)[0];G
= img_RGB
.at
<cv
::Vec3b
>(i
, j
)[1];R
= img_RGB
.at
<cv
::Vec3b
>(i
, j
)[2];if ((B
>= G
) && (G
>= R
)) {V
= B
;m
= R
;} else if ((B
>= G
) && (G
< R
) && (B
>= R
)) {V
= B
;m
= G
;} else if ((B
>= G
) && (G
< R
) && (B
< R
)) {V
= R
;m
= G
;} else if ((B
< G
) && (G
< R
)) {V
= R
;m
= B
;} else if ((B
< G
) && (G
>= R
) && (B
>= R
)) {V
= G
;m
= R
;} else {V
= G
;m
= B
;}if (V
> m
) {S
= (int)((V
- m
) / V
);} else {S
= 0;}if (V
== m
) {H
= 0;} else if (V
== R
) {H
= (int)(60 * (G
- B
) / (V
- m
));} else if (V
== G
) {H
= (int)(120 + 60 * (B
- R
) / (V
- m
));} else {H
= (int)(240 + 60 * (R
- G
) / (V
- m
));}if (H
< 0) {H
= H
+ 360;}img_HSV
.at
<cv
::Vec3b
>(i
, j
)[0] = H
;img_HSV
.at
<cv
::Vec3b
>(i
, j
)[1] = S
;img_HSV
.at
<cv
::Vec3b
>(i
, j
)[2] = V
;}}}
__global__
void global_RGB_to_HSV(uchar3
* d_image_RGB
, uchar3
* d_image_HSV
,int height
, int width
){int R
, G
, B
;int V
; int m
; int S
; int H
; for (int row
= blockDim
.y
* blockIdx
.y
+ threadIdx
.y
; row
< height
; row
= row
+ gridDim
.y
* blockDim
.y
) {for (int col
= blockDim
.x
* blockIdx
.x
+ threadIdx
.x
; col
< width
; col
= col
+ gridDim
.x
* blockDim
.x
) {B
= d_image_RGB
[row
* width
+ col
].x
;G
= d_image_RGB
[row
* width
+ col
].y
;R
= d_image_RGB
[row
* width
+ col
].z
;if ((B
>= G
) && (G
>= R
)) {V
= B
;m
= R
;} else if ((B
>= G
) && (G
< R
) && (B
>= R
)) {V
= B
;m
= G
;} else if ((B
>= G
) && (G
< R
) && (B
< R
)) {V
= R
;m
= G
;} else if ((B
< G
) && (G
< R
)) {V
= R
;m
= B
;} else if ((B
< G
) && (G
>= R
) && (B
>= R
)) {V
= G
;m
= R
;} else {V
= G
;m
= B
;}if (V
> m
) {S
= (int)((V
- m
) / V
);} else {S
= 0;}if (V
== m
) {H
= 0;} else if (V
== R
) {H
= (int)(60 * (G
- B
) / (V
- m
));} else if (V
== G
) {H
= (int)(120 + 60 * (B
- R
) / (V
- m
));} else {H
= (int)(240 + 60 * (R
- G
) / (V
- m
));}if (H
< 0) {H
= H
+ 360;}d_image_HSV
[row
* width
+ col
].x
= H
;d_image_HSV
[row
* width
+ col
].y
= S
;d_image_HSV
[row
* width
+ col
].z
= V
;}}
}
void enhance_HSV(cv
::Mat
&image_hsv
) {int row
= image_hsv
.rows
;int col
= image_hsv
.cols
;for (int i
= 0; i
< row
; i
= i
+ 1) {for (int j
= 0; j
< col
; j
= j
+ 1) {if (image_hsv
.at
<cv
::Vec3b
>(i
, j
)[2] >= 205) {image_hsv
.at
<cv
::Vec3b
>(i
, j
)[2] = 255;} else {image_hsv
.at
<cv
::Vec3b
>(i
, j
)[2] = 0;}}}
}
__device__
void device_enhance_HSV(uchar3
* d_image_HSV
, int height
, int width
) {for (int row
= blockDim
.y
* blockIdx
.y
+ threadIdx
.y
; row
< height
; row
= row
+ gridDim
.y
* blockDim
.y
) {for (int col
= blockDim
.x
* blockIdx
.x
+ threadIdx
.x
; col
< width
; col
= col
+ gridDim
.x
* blockDim
.x
) {if (d_image_HSV
[row
* width
+ col
].z
>= 205) {d_image_HSV
[row
* width
+ col
].z
= 255;} else {d_image_HSV
[row
* width
+ col
].z
= 0;}}}
}void HSV_to_gray(const cv
::Mat image_hsv
, cv
::Mat
&image_gray
, cv
::Mat
&image_gray_
) {int row
= image_hsv
.rows
;int col
= image_hsv
.cols
;for (int i
= 0; i
< row
; i
= i
+ 1) {for (int j
= 0; j
< col
; j
= j
+ 1) {if (image_hsv
.at
<cv
::Vec3b
>(i
, j
)[2] == 255) {image_gray
.at
<uchar
>(i
, j
) = 255;} else {image_gray
.at
<uchar
>(i
, j
) = 0;}}}for (int i
= 1; i
< row
- 1; i
= i
+ 1) {for (int j
= 1; j
< col
- 1; j
= j
+ 1) {if (image_gray
.at
<uchar
>(i
- 1, j
- 1) +image_gray
.at
<uchar
>(i
- 1, j
) +image_gray
.at
<uchar
>(i
- 1, j
+ 1) +image_gray
.at
<uchar
>(i
, j
- 1) +image_gray
.at
<uchar
>(i
, j
+ 1) +image_gray
.at
<uchar
>(i
+ 1, j
- 1) +image_gray
.at
<uchar
>(i
+ 1, j
) +image_gray
.at
<uchar
>(i
+ 1, j
+ 1) > 1000) {image_gray_
.at
<uchar
>(i
, j
) = 255;} else {image_gray_
.at
<uchar
>(i
, j
) = 0;}}}
}
__device__
void device_HSV_to_gray(const uchar3
* d_image_HSV
, uchar
* d_image_gray
, uchar
* d_image_gray_
, int height
, int width
) {for (int row
= blockDim
.y
* blockIdx
.y
+ threadIdx
.y
; row
< height
; row
= row
+ gridDim
.y
* blockDim
.y
) {for (int col
= blockDim
.x
* blockIdx
.x
+ threadIdx
.x
; col
< width
; col
= col
+ gridDim
.x
* blockDim
.x
) {if (d_image_HSV
[row
* width
+ col
].z
== 255) {d_image_gray
[row
* width
+ col
] = 255;} else {d_image_gray
[row
* width
+ col
] = 0;}}}__syncthreads();for (int row
= blockDim
.y
* blockIdx
.y
+ threadIdx
.y
; row
< height
; row
= row
+ gridDim
.y
* blockDim
.y
) {for (int col
= blockDim
.x
* blockIdx
.x
+ threadIdx
.x
; col
< width
; col
= col
+ gridDim
.x
* blockDim
.x
) {if (d_image_gray
[(row
- 1) * width
+ col
- 1] +d_image_gray
[(row
- 1) * width
+ col
] +d_image_gray
[(row
- 1) * width
+ col
+ 1] +d_image_gray
[row
* width
+ col
- 1] +d_image_gray
[row
* width
+ col
+ 1] +d_image_gray
[(row
+ 1) * width
+ col
- 1] +d_image_gray
[(row
+ 1) * width
+ col
] +d_image_gray
[(row
+ 1) * width
+ col
+ 1] > 1000) {d_image_gray_
[row
* width
+ col
] = 255;} else {d_image_gray_
[row
* width
+ col
] = 0;}}}
}
__global__
void global_do(uchar3
* d_image_RGB
, uchar3
* d_image_HSV
, uchar
* d_image_gray
, uchar
* d_image_gray_
, int height
, int width
) {device_enhance_HSV(d_image_HSV
, height
, width
);device_HSV_to_gray(d_image_HSV
, d_image_gray
, d_image_gray_
, height
, width
);
}
int main()
{cv
::Mat image_RGB
= cv
::imread("../../bgrtohsv/front.jpg");int height
= image_RGB
.rows
;int width
= image_RGB
.cols
;cv
::Mat
image_HSV(height
, width
, CV_8UC3
);cv
::Mat
image_gray(height
, width
, CV_8UC1
);cv
::Mat
image_gray_(height
, width
, CV_8UC1
);size_t size_image_RGB
= sizeof(uchar3
) * height
* width
;size_t size_image_HSV
= sizeof(uchar3
) * height
* width
;size_t size_image_gray
= sizeof(uchar
) * height
* width
;size_t size_image_gray_
= sizeof(uchar
) * height
* width
;uchar3
* d_image_RGB
= NULL;uchar3
* d_image_HSV
= NULL;uchar
* d_image_gray
= NULL;uchar
* d_image_gray_
= NULL;cudaMalloc((void**)&d_image_RGB
, size_image_RGB
);cudaMalloc((void**)&d_image_HSV
, size_image_HSV
);cudaMalloc((void**)&d_image_gray
, size_image_gray
);cudaMalloc((void**)&d_image_gray_
, size_image_gray_
);cudaMemcpy(d_image_RGB
, image_RGB
.data
, size_image_RGB
, cudaMemcpyHostToDevice
);cudaMemcpy(d_image_HSV
, image_HSV
.data
, size_image_HSV
, cudaMemcpyHostToDevice
);cudaMemcpy(d_image_gray
, image_gray
.data
, size_image_gray
, cudaMemcpyHostToDevice
);cudaMemcpy(d_image_gray_
, image_gray_
.data
, size_image_gray_
, cudaMemcpyHostToDevice
);dim3
dimGrid(16, 16, 1);dim3
dimBlock(32, 32, 1);global_RGB_to_HSV
<< <dimGrid
, dimBlock
>> >(d_image_RGB
, d_image_HSV
, height
, width
);cudaDeviceSynchronize();global_do
<< <dimGrid
, dimBlock
>> >(d_image_RGB
, d_image_HSV
, d_image_gray
, d_image_gray_
, height
, width
);cudaDeviceSynchronize(); cudaMemcpy(image_RGB
.data
, d_image_RGB
, size_image_RGB
, cudaMemcpyDeviceToHost
);cudaMemcpy(image_HSV
.data
, d_image_HSV
, size_image_HSV
, cudaMemcpyDeviceToHost
);cudaMemcpy(image_gray
.data
, d_image_gray
, size_image_gray
, cudaMemcpyDeviceToHost
);cudaMemcpy(image_gray_
.data
, d_image_gray_
, size_image_gray_
, cudaMemcpyDeviceToHost
);cudaDeviceSynchronize();
cv
::imshow("image_HSV", image_HSV
);cv
::imshow("image_gray", image_gray
);cv
::imshow("image_gray_", image_gray_
);cv
::waitKey(0);cv
::imwrite("../../bgrtohsv/image_HSV.jpg", image_HSV
);cv
::imwrite("../../bgrtohsv/image_gray.jpg", image_gray
);cv
::imwrite("../../bgrtohsv/image_gray_.jpg", image_gray_
);cudaFree(d_image_RGB
);cudaFree(d_image_HSV
);cudaFree(d_image_gray
);cudaFree(d_image_gray_
);return 0;
}
原圖(image_RGB):image_HSV:image_gray:image_gray_:最后兩張圖是有差別的。
總結(jié):
1.使用CUDA處理二維圖像的萬(wàn)能公式:
for (int row
= blockDim
.y
* blockIdx
.y
+ threadIdx
.y
; row
< height
; row
= row
+ gridDim
.y
* blockDim
.y
) {for (int col
= blockDim
.x
* blockIdx
.x
+ threadIdx
.x
; col
< width
; col
= col
+ gridDim
.x
* blockDim
.x
) {do_something();}}
2.__device__定義的函數(shù)不能在main()函數(shù)里執(zhí)行,甚至不能分配計(jì)算資源,需要放到__global__中執(zhí)行,再在main()中執(zhí)行。這條不對(duì)!!!
__global__
void global_abc(uchar3
* d_image_HSV
, uchar
* d_image_gray
, uchar
* d_image_gray_
, int height
, int width
) {device_enhance_HSV(d_image_HSV
, height
, width
);device_HSV_to_gray(d_image_HSV
, d_image_gray
, d_image_gray_
, height
, width
);
}
CMakeLists.txt
cmake_minimum_required(VERSION
2.8)project(bgrtohsv
)set(CMAKE_CXX_STANDARD
11)
set(CMAKE_CXX_STANDARD_REQUIRED ON
)include_directories(include
$
{CUDA_INCLUDE_DIRS
}
$
{OpenCV_INCLUDE_DIRS
}
)link_directories($
{OpenCV_LIBRARY_DIRS
})find_package(CUDA REQUIRED
)
find_package(OpenCV REQUIRED
)#INCLUDE(/home/psdz/cmake-3.9.0/Modules/FindCUDA.cmake)FILE(GLOB SOURCES
"*.cu" "*.cpp" "*.c" "*.h")set(CUDA_NVCC_FLAGS
"-g -G")CUDA_ADD_EXECUTABLE($
{PROJECT_NAME
} main
.cu
)target_link_libraries($
{PROJECT_NAME
} $
{OpenCV_LIBS
})#add_executable(${PROJECT_NAME} "main.cpp")
總結(jié)
以上是生活随笔為你收集整理的车道线识别之——增强黄色车道线的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。