2016-11-24 3 views
0

Je suis nouveau à openCV, je me suis mis dans les échantillons fournis pour Android. Mes objectifs sont de détecter les blobs de couleur, donc j'ai commencé avec un échantillon de détection de couleur-blob.Détecter encre noire sur le papier - Opencv Android

Je convertis l'image couleur en niveaux de gris et ensuite le seuillage en utilisant un seuil binaire.

L'arrière-plan est blanc, les tâches sont noires. Je veux détecter ces blobs noirs. Aussi, je voudrais dessiner leur contour en couleur mais je ne suis pas capable de le faire car l'image est en noir et blanc. J'ai réussi à obtenir ceci en niveaux de gris mais je ne préfère pas comment les contours sont dessinés, c'est comme si la tolérance de couleur était trop élevée et le contour plus grand que le blob réel (peut-être que les blobs sont trop petits?). Je suppose que cette 'tolérance' dont je parle a quelque chose à voir avec setHsvColor mais je ne comprends pas très bien cette méthode.

Merci d'avance! Cordialement

MISE À JOUR PLUS D'INFO

L'image que je veux suivre est de scissions d'encre. Imaginez un morceau de papier blanc avec des fentes d'encre noire. En ce moment je le fais en temps réel (vue caméra). L'application réelle prendrait une photo et analyser cette image. Comme je l'ai dit ci-dessus, j'ai pris l'échantillon de détection de couleur-blob (android) à partir du repo openCV GitHub. Et j'ajoute ce code dans la méthode onCameraFrame (afin de le convertir en noir et blanc en temps réel) Le convertion est fait, donc je ne me dérange pas si l'encre est noir, bleu, rouge:

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); 
/**************************************************************************/ 

Ce n'est peut-être pas la meilleure solution, mais cela fonctionne.

Maintenant, je veux détecter les taches noires (fentes d'encre). Je suppose qu'ils sont détectés car le Logcat (entrée de journal de l'application exemple) jette le nombre de contours détectés, mais je ne peux pas les voir car l'image est en noir et blanc et je veux que le contour soit rouge, par exemple.

est ici une image par exemple: - enter image description here

Et voici ce que je me sers RGB (couleur blob-détection comme il est, pas noir et blanc image). Remarquez comment les petits blobs ne sont pas détectés. (Est-il possible de les détecter? Ou sont-ils trop petits?) enter image description here

Merci pour votre aide! Si vous avez besoin de plus d'informations, je serais heureux de mettre à jour cette question

MISE À JOUR: repo GitHub de l'échantillon couleur blob-détection (deuxième image)

GitHub Repo of openCV sample for Android

+0

Salut, votre question est tout à fait uninformative. S'il vous plaît télécharger les images d'entrée et ce que votre traitement a conduit à. Cela aidera à comprendre la question. A titre d'exemple, voir cette question: http://stackoverflow.com/q/10168686/1874627 – saurabheights

+0

@saurabheights merci pour votre commentaire. Je vais mettre à jour la question avec plus d'infos et aussi des extraits de code – sebasira

+0

Ok, il y a peu de choses que je peux suggérer. Que les petits ou grands blobs ne soient pas un problème, tant qu'il y a un bon contraste. Si vous pouvez trouver la zone où la plupart des pixels sont blancs (vérifiez le composant connecté), vous aurez votre région de papier. En cela, si vous trouvez une sous-région à être noire (bien au-dessous de l'intensité moyenne de la région de papier), vous trouverez tous vos blobs. Pour dessiner le contour, vous avez besoin de la coque convexe de la région noire trouvée. En outre, pouvez-vous télécharger le code (ou un lien vers celui-ci) pour la façon dont vous avez atteint la deuxième sortie d'image. Il est tard ici, donc je vais vérifier ça demain. Merci pour la bonne mise à jour. – saurabheights

Répondre

0

La solution est basée sur une combinaison d'adaptation Le seuillage d'image et l'utilisation de l'algorithme de composants connectés.

Hypothèse - Le papier est la zone la plus éclairée de l'image alors que les taches d'encre sur le papier sont les plus sombres.

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) 

L'image d'entrée

The Input Image

Image Masked de seuillage et inverse.

Masked Image

Utilisation du composant connecté.

CC Image

Superposition de sortie du composant connecté sur l'image d'entrée.

Output Image

+0

Après avoir posté, j'ai remarqué le grand rectangle orange. Dans le cas où vous voulez l'ignorer, il devrait s'agir d'une estimation de zone simple par rapport à l'image. Ou comme la vérification du rapport d'aspect, un blob aura presque la même hauteur/largeur. Une question, à quoi cela sert-il? – saurabheights

+0

@sebasira Ça fait partie de l'esthétique, hehe. Pourquoi utiliser une boîte noire lorsque vous pouvez utiliser l'arc-en-ciel! En outre, une boîte noire autour d'un blob d'encre noire ne sera pas très discernable. – saurabheights

+0

@sebasira: Pourriez-vous me mettre au courant de comment ça s'est passé? C'est la précision ainsi que les pièges? Prenez votre temps pour répondre, pas pressé. – saurabheights