Обнаружение черных чернил на бумаге - Android Opencv

Я новичок в openCV, я вхожу в примеры для Android.

Мои цели - обнаружение цветных пятен, поэтому я начал с образца обнаружения цветовых пятен.

Я конвертирую цветное изображение в градации серого, а затем устанавливаю пороговое значение с использованием двоичного порога

Фон белый, капли чёрные. Я хочу обнаружить эти черные пятна. Кроме того, я хотел бы нарисовать их контур в цвете, но я не могу этого сделать, потому что изображение черно-белое.

Мне удалось сделать это в оттенках серого, но я не предпочитаю, как нарисованы контуры, это похоже на слишком высокую толерантность к цвету, и контур больше, чем фактический шарик (может быть, шарики слишком малы?). Я предполагаю, что эта "терпимость", о которой я говорю, имеет отношение к setHsvColor, но я не совсем понимаю этот метод.

Заранее спасибо! С уважением

ОБНОВИТЬ БОЛЬШЕ ИНФОРМАЦИИ

Изображение, которое я хочу отслеживать, имеет чернильные пятна. Представьте себе белый лист бумаги с черными чернилами. Прямо сейчас я делаю это в режиме реального времени (вид с камеры). Фактическое приложение будет делать снимок и анализировать его.

Как я уже говорил выше, я взял образец обнаружения цветных пятен (android) из репозитория openCV GitHub. И я добавляю этот код в метод onCameraFrame (для преобразования его в черно-белое в режиме реального времени). Преобразование сделано, поэтому я не против, если чернила черные, синие, красные:

mRgba = inputFrame.rgba();
/**************************************************************************/
/** BLACK AND WHITE **/
// Convert to Grey
Imgproc.cvtColor(inputFrame.gray(), mRgba, Imgproc.COLOR_GRAY2RGBA, 4);

Mat blackAndWhiteMat = new Mat ( H, W, CvType.CV_8U, new Scalar(1));
double umbral = 100.0;
Imgproc.threshold(mRgba, blackAndWhiteMat , umbral, 255, Imgproc.THRESH_BINARY);

// convert back to bitmap for displaying
Bitmap resultBitmap = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
blackAndWhiteMat.convertTo(blackAndWhiteMat, CvType.CV_8UC1);
Utils.matToBitmap(blackAndWhiteMat, resultBitmap);
/**************************************************************************/

Это может быть не лучшим способом, но это работает.

Теперь я хочу обнаружить черные пятна (расщепление чернил). Я предполагаю, что они обнаружены, потому что Logcat (запись в журнале примера приложения) выбрасывает количество обнаруженных контуров, но я не могу их увидеть, потому что изображение черно-белое, и я хочу, чтобы контур был красным, например.

Вот пример изображения:-

И вот что я получаю, используя RGB (распознавание цветных пятен как есть, а не черно-белое изображение). Обратите внимание, как маленькие капли не обнаружены. (Можно ли их обнаружить? Или они слишком маленькие?)

Спасибо за вашу помощь! Если вам нужна дополнительная информация, я с удовольствием обновлю этот вопрос

ОБНОВЛЕНИЕ: GitHub репо образца обнаружения цветных пятен (второе изображение)

GitHub Репо образца openCV для Android

1 ответ

Решение

Решение основано на комбинации адаптивного порогового изображения и использования алгоритма связанного компонента.

Предположение - бумага является наиболее освещенной областью изображения, тогда как пятна чернил на бумаге являются самыми темными областями.

from random import Random
import numpy as np
import cv2

def random_color(random):
    """
    Return a random color
    """
    icolor = random.randint(0, 0xFFFFFF)
    return [icolor & 0xff, (icolor >> 8) & 0xff, (icolor >> 16) & 0xff]

#Read as Grayscale
img = cv2.imread('1-input.jpg', 0)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)

# Gaussian to remove noisy region, comment to see its affect.
img = cv2.medianBlur(img,5)

#Find average intensity to distinguish paper region
avgPixelIntensity = cv2.mean( img )
print "Average intensity of image: ", avgPixelIntensity[0]

# Generate mask to distinguish paper region
#0.8 - used to ignore ill-illuminated region of paper
mask = cv2.inRange(img, avgPixelIntensity[0]*0.8, 255) 
mask = 255 - mask
cv2.imwrite('2-maskedImg.jpg', mask)

#Approach 1
# You need to choose 4 or 8 for connectivity type(border pixels)
connectivity = 8
# Perform the operation
output = cv2.connectedComponentsWithStats(mask, connectivity, cv2.CV_8U)
# The first cell is the number of labels
num_labels = output[0]
# The second cell is the label matrix
labels = output[1]
# The third cell is the stat matrix
stats = output[2]
# The fourth cell is the centroid matrix
centroids = output[3]

cv2.imwrite("3-connectedcomponent.jpg", labels)
print "Number of labels", num_labels, labels

# create the random number
random = Random()

for i in range(1, num_labels):
    print stats[i, cv2.CC_STAT_LEFT], stats[i, cv2.CC_STAT_TOP], stats[i, cv2.CC_STAT_WIDTH], stats[i, cv2.CC_STAT_HEIGHT]
    cv2.rectangle(cimg, (stats[i, cv2.CC_STAT_LEFT], stats[i, cv2.CC_STAT_TOP]), 
        (stats[i, cv2.CC_STAT_LEFT] + stats[i, cv2.CC_STAT_WIDTH], stats[i, cv2.CC_STAT_TOP] + stats[i, cv2.CC_STAT_HEIGHT]), random_color(random), 2)

cv2.imwrite("4-OutputImage.jpg", cimg)

Входное изображение

Входное изображение

Маскированное изображение от операции порогового значения и инвертирования.

Замаскированное изображение

Использование подключенного компонента.

CC Image

Наложение вывода подключенного компонента на входное изображение.

Выходное изображение

Другие вопросы по тегам