Détection de bord sur fond coloré à L'aide D'OpenCV

j'utilise le code suivant pour détecter les contours d'un document donné.

private Mat edgeDetection(Mat src) {
    Mat edges = new Mat();
    Imgproc.cvtColor(src, edges, Imgproc.COLOR_BGR2GRAY);
    Imgproc.GaussianBlur(edges, edges, new Size(5, 5), 0);
    Imgproc.Canny(edges, edges, 10, 30);
    return edges;
}

et puis je peux trouver le document de ce edges en trouvant le plus grand contour de ceci.

mon problème est que je peux trouver le document du pic suivant:

enter image description here

mais pas du pic suivant:

enter image description here

Comment puis-je améliorer cette détection de bord?

2
demandé sur halfer 2017-12-20 08:06:34

2 réponses

j'utilise Python, mais l'idée principale est la même.

si vous faites directement cvtColor: BGR -> gray pour img2, alors vous devez échouer. Parce que le gris devient difficile de distinguer les régions:

enter image description here


réponses:

  1. Détecter Segment de Couleur dans une image
  2. détection de contours dans opencv android
  3. OpenCV C++ / Obj-C: détection d'une feuille de papier / détection carrée

dans votre image , le papier est white , tandis que le fond est colored . Donc, il est préférable de détecter le papier est Saturation(饱和度) canal HSV color space . Pour HSV, se référer à https://en.wikipedia.org/wiki/HSL_and_HSV#Saturation .


étapes Principales:

  1. Lire BGR
  2. Convertissez l'image de bgr en hsv espace
  3. Seuil de la S canal
  4. puis trouver le contour externe max(ou faire Canny , ou HoughLines comme vous voulez, je choisis findContours ), approx pour obtenir coin.

C'est le premier résultat:

enter image description here

C'est le deuxième résultat:

enter image description here

le code Python (Python 3.5 + OpenCV 3.3):

#!/usr/bin/python3
# 2017.12.20 10:47:28 CST
# 2017.12.20 11:29:30 CST

import cv2
import numpy as np

##(1) read into  bgr-space
img = cv2.imread("test2.jpg")

##(2) convert to hsv-space, then split the channels
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv)

##(3) threshold the S channel using adaptive method(`THRESH_OTSU`) or fixed thresh
th, threshed = cv2.threshold(s, 50, 255, cv2.THRESH_BINARY_INV)

##(4) find all the external contours on the threshed S
_, cnts, _ = cv2.findContours(threshed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
canvas  = img.copy()
#cv2.drawContours(canvas, cnts, -1, (0,255,0), 1)

## sort and choose the largest contour
cnts = sorted(cnts, key = cv2.contourArea)
cnt = cnts[-1]

## approx the contour, so the get the corner points
arclen = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.02* arclen, True)
cv2.drawContours(canvas, [cnt], -1, (255,0,0), 1, cv2.LINE_AA)
cv2.drawContours(canvas, [approx], -1, (0, 0, 255), 1, cv2.LINE_AA)

## Ok, you can see the result as tag(6)
cv2.imwrite("detected.png", canvas)
8
répondu Silencer 2017-12-20 12:20:50

dans OpenCV il y a une fonction appelée dilate qui va assombrir les lignes. donc, essayez le code comme ci-dessous.

private Mat edgeDetection(Mat src) {
    Mat edges = new Mat();
    Imgproc.cvtColor(src, edges, Imgproc.COLOR_BGR2GRAY);
    Imgproc.dilate(edges, edges, Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(10, 10)));
    Imgproc.GaussianBlur(edges, edges, new Size(5, 5), 0);
    Imgproc.Canny(edges, edges, 15, 15 * 3);
    return edges;
}
1
répondu Prakash 2017-12-20 05:23:26