📜 ⬆️ ⬇️

OpenCV. Search for road signs using contour analysis in Android

Hi Habr!

I want to share my own implementation of the road sign search algorithm.

Why contour analysis?
')
Contour analysis has a rather weak resistance to interference, but the simplicity and speed allowed us to apply this approach quite successfully.



However, in practice, it turned out to be quite difficult to implement the search for the necessary coefficients on the Android platform (I did not try to use OpenCV widgets, instead divided the screen into frames, where the settings are on the left, the video from the back camera is on the right). The specific implementation of the UI and project logic is available at the link below.

The sequence of road sign search operations is as follows:


Not to say that it works well in real-world conditions (perhaps, the detection algorithm is not the best, but it turned out to be the easiest to use). And there are difficulties in finding the optimal coefficients (there was plenty of "hunting" for road signs in my city; I even met signs that had faded from the sun, there was no red on them at all).

But simplicity is pleasing to the eye, so it is quite possible to find an application to contour analysis, for example, in robotics.

From the additional buns on the experience of using OpenCV in Android:

Rotate camera image if it is flipped
 extern "C" JNIEXPORT void JNICALL Java_ru_dksta_prohibitingsigndetector_ActivityMain_rotation(JNIEnv /* *env */, jclass /* activity */, jlong matAddress, jint angle) { CV_Assert(angle % 90 == 0 && angle <= 360 && angle >= -360); cv::Mat* mat = (cv::Mat*) matAddress; if (angle == 180 || angle == -180) { cv::flip(*mat, *mat, -1); } } 


Implementing Salt & Pepper Noise
 extern "C" JNIEXPORT void JNICALL Java_ru_dksta_prohibitingsigndetector_ActivityMain_saltPepperNoise(JNIEnv /* *env */, jclass /* activity */, jlong matAddress) { cv::Mat* mat = (cv::Mat*) matAddress; cv::Mat noise = cv::Mat::zeros((*mat).rows, (*mat).cols, CV_8U); cv::randu(noise, 0, 255); cv::Mat black = noise < 30; cv::Mat white = noise > 225; (*mat).setTo(255, white); (*mat).setTo(0, black); } 


Displaying video from a camera with processing in the 'picture in picture' mode
 if (secondView) { cv::Mat miniView = colorDilated.clone(); cv::cvtColor(miniView, miniView, cv::COLOR_GRAY2RGB); cv::resize(miniView, miniView, cv::Size(), 0.6, 0.6, cv::INTER_LINEAR); cv::Size miniSize = miniView.size(); cv::Size maxSize = original.size(); int startY = maxSize.height - miniSize.height; for (int y = startY; y < maxSize.height; y++) { for (int x = 0; x < miniSize.width; x++) { (*(cv::Mat*)matAddress).at<cv::Vec3b>(cv::Point(x, y)) = miniView.at<cv::Vec3b>(cv::Point(x, y - startY)); } } } 


Writing text in OpenCV
 cv::Mat* mat = (cv::Mat*)matAddress; int textStartY = TEXT_LINE_HEIGHT; std::ostringstream output; output << std::setw(2) << std::setfill('0') << fpsCount << " FPS"; cv::putText(*mat, output.str(), cv::Point(TEXT_START_X, textStartY), FONT_FACE, FONT_SCALE, GREEN, TEXT_THICKNESS); output.seekp(0); textStartY += TEXT_LINE_HEIGHT; cv::putText(*mat, getLayerTypeDesc(layerType), cv::Point(TEXT_START_X, textStartY), FONT_FACE, FONT_SCALE, GREEN, TEXT_THICKNESS); 


Link to project

Source: https://habr.com/ru/post/339506/


All Articles