Трудно отфильтровать пунктирный рисунок, как вы можете видеть. Это явно перекрывает текст. Я вижу по крайней мере два варианта: 1) Использовать периодическую c природу паттерна и выполнять частотную фильтрацию . 2) Попробуйте более простой подход, используя морфологическое попадание или промах для целевых пикселей с целью их выделения.
Давайте рассмотрим вариант 2. Шум имеет очень характерную картину. Если вы работаете с двоичным изображением, в котором все капли окрашены в белый цвет, то шаблон, который вы ищете, это белый пиксель (1) , окруженный 8 черными пикселями (0) :
[ 0, 0, 0 ]
[ 0, 1, 0 ]
[ 0, 0, 0 ]
Операция попадания и пропуска может использоваться для определения местоположения и выделения шаблонов пикселей. Вот хороший пост, если вы хотите узнать о нем больше. А сейчас давайте поработаем с кодом:
//Read the input image, as normal:
std::string imagePath = "C://opencvImages//tableTest.png";
cv::Mat testImage = cv::readImage( imagePath );
//Convert the image to grayscale:
cv::Mat grayImage;
cv::cvtColor( testImage, grayImage, cv::COLOR_BGR2GRAY );
//Get the binary image via otsu:
cv::Mat binaryImage;
cv::threshold( grayImage, binaryImage, 0, 255,cv::THRESH_OTSU );
//Invert the image, as we will be working on white blobs:
binaryImage = 255 - binaryImage;
//Prepare the target kernel. This is where you define the pattern of
//pixels you are looking for
//Keep in mind that -1 -> black and 1 -> white
cv::Mat kernel = ( cv::Mat_<int>(3, 3) <<
-1, -1, -1,
-1, 1, -1,
-1, -1, -1
);
//perform the hit or miss operation:
cv::Mat hitMissMask;
cv::morphologyEx( binaryImage, hitMissMask, cv::MORPH_HITMISS, kernel );
Вот маска, которую вы получите:
Теперь просто вычтите эту маску к исходному (двоичному) изображению, и вы получите:
Как видите, часть заголовка столбца мешает операция. Если вам нужен белый фон и черные пятна, просто инвертируйте изображение: