У меня есть несколько образцов из цветных изображений, которые я должен превратить в двоичный файл. Я получил лучшие результаты с помощью адаптивный порог.
Числа очень хороши, четко определены, но вокруг шумно, и эти «вертикальные линии», которые разделяют каждое число, заканчиваются тем, что их читают, например, как номер 1 для инструмента OCR.
Тогда я заметил, что вокруг цифр изображение чистое. Я подумал, смогу ли я вырезать только цифры (до или после того, как сделаю картинку черно-белой?), А затем «вставить» эти цифры на белый фон.
Я пытался подать заявку эрозия а также расширение, но все еще много оставшихся «точек». Если бы я мог сделать то, что я думаю (см. Выше), это уменьшит эрозию / расширение и увеличит «чистку» вокруг числа перед разрезом, я не знаю.
Это возможно? Я имел какой-то смысл? Если да, как я могу сделать это с помощью OpenCV? Какие-либо предложения?
Некоторые изображения, которые я использую:
Замечания: Изображения выше не прошли процессы эрозии и / или расширения, только адаптивный порог.
Обновить:
@ Mahm00d, я попробовал то, что вы сказали с первым изображением, и я получил изображение ниже, что очень хорошо, но проблема с отражением в первых двух числах сохраняется. Есть ли способ это исправить? Я применил адаптивный порог, но изображение остается довольно шумным.
GaussianBlur + Treshold с флагом OTSU:
GaussianBlur + адаптивный порог:
Часто полезно сначала использовать некоторые шумодав техника, как Гауссово / медианное размытие до прохождения порога и морфологии:
(Код на Java)
Imgproc.cvtColor(inputMat, gMat, Imgproc.COLOR_RGB2GRAY);
// Gaussian blur : 21x21 window, sigma = 50.0 (select these accordignly)
Imgproc.GaussianBlur(gMat, gMat, new Size(21.0, 21.0), 50.0);
// Otsu thresholding (or any other thresholding techinique...)
Imgproc.threshold(gMat, gMat, 0, 255, Imgproc.THRESH_OTSU | Imgproc.THRESH_BINARY);
Ваш вывод:
Выше кода:
Обновить:
Этим проблемам часто нужно немного поиграть со значениями параметров, чтобы получить хороший результат и достичь оптимальных значений. В случае второго изображения, вот код, который я использовал (адаптивный порог), чтобы получить лучший результат:
Imgproc.GaussianBlur(inImg, inImg, new Size(21.0, 21.0), 50.0);
Imgproc.adaptiveThreshold(inImg, inImg, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 111, -20);
Результат:
Конечно, это не идеально, но по крайней мере отражение удаляется. Кроме того, морфологические процессы могут помочь привести к лучшим результатам.
Одним из решений было бы применить расширение и эрозию и найти все контуры, которые меньше, чем X-пиксели, и залить их белым цветом:
int main()
{
// Load the image as a Grayscale
Mat image = imread("image.jpg", CV_LOAD_IMAGE_GRAYSCALE);
// Threshold the image
image = image > 120;
// Create bigger image with image width and height + 10 pixels
Mat image_big = Mat::zeros( image.size().height + 10, image.size().width + 10, CV_8UC1 );
// Set bigger image to be all white
image_big.setTo(255);
Mat image_big_copy;
// This may vary, you must find it for yourself
// Dilate image 4 times and erode once
dilate(image, image, Mat(), Point(-1,-1), 4);
erode(image, image, Mat(), Point(-1,-1));
// Copy image in the center of bigger image so you left 5px around image blank/white
// Create a new ROI that points to center of the bigger image
Mat image_big_roi = image_big( Rect(Point(5, 5), Size(image.size())) );
// Copy image to the bigger image ROI
addWeighted(image_big_roi, 0., image, 1., 0., image_big_roi);
// Create a data copy of image_big
image_big.copyTo(image_big_copy);
// Find all contours in a given image and store them in contours
vector<vector<Point> > contours;
findContours(image_big_copy, contours, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE);
for( int i = 0; i < contours.size(); i++ )
{
// This is your condition to filter out unwanted contours etc.
// For every contour if its area is bigger/smaller than the sum of pixels
if ( fabs(contourArea(Mat(contours[i]))) < 800 )
{
// Fill a contour with white color
drawContours(image_big, contours, i, Scalar(255), CV_FILLED);
}
}
imshow("Image original", image);
imshow("Image edited", image_big);
waitKey(0);
return 0;
}
Исходное изображение:
После: