web-dev-qa-db-fra.com

détecter un rectangle dans l'image et rogner

J'ai beaucoup d'images numérisées de chiffres manuscrits à l'intérieur d'un rectangle (petit). [! [Like This [1]] [1]

Aidez-moi à rogner chaque image contenant des chiffres et à les sauvegarder en donnant le même nom à chaque ligne. 

Modifier

import cv2

img = cv2.imread('Data\Scan_20170612_4.jpg')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.bilateralFilter(gray, 11, 17, 17)
edged = cv2.Canny(gray, 30, 200)

_, contours, hierarchy = cv2.findContours(edged, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

i = 0
for c in contours:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.09 * peri, True)

    if len(approx) == 4:
        screenCnt = approx
        cv2.drawContours(img, [screenCnt], -1, (0, 255, 0), 3)
        cv2.imwrite('cropped\\' + str(i) + '_img.jpg', img)

        i += 1
3
utkarsh

Voici ma version

import cv2
import numpy as np

fileName = ['9','8','7','6','5','4','3','2','1','0']

img = cv2.imread('Data\Scan_20170612_17.jpg')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = cv2.bilateralFilter(gray, 11, 17, 17)

kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(gray,kernel,iterations = 2)
kernel = np.ones((4,4),np.uint8)
dilation = cv2.dilate(erosion,kernel,iterations = 2)

edged = cv2.Canny(dilation, 30, 200)

_, contours, hierarchy = cv2.findContours(edged, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

rects = [cv2.boundingRect(cnt) for cnt in contours]
rects = sorted(rects,key=lambda  x:x[1],reverse=True)


i = -1
j = 1
y_old = 5000
x_old = 5000
for rect in rects:
    x,y,w,h = rect
    area = w * h

    if area > 47000 and area < 70000:

        if (y_old - y) > 200:
            i += 1
            y_old = y

        if abs(x_old - x) > 300:
            x_old = x
            x,y,w,h = rect

            out = img[y+10:y+h-10,x+10:x+w-10]
            cv2.imwrite('cropped\\' + fileName[i] + '_' + str(j) + '.jpg', out)

            j+=1
2
utkarsh

C'est une chose facile si vous essayez. Voici ma sortie - (l'image et son un petit peu)

 enter image description here

Ce que j'ai fait?

  1. Redimensionner l'image d'abord parce qu'elle était trop grande dans mon écran
  2. Erode, Dilate pour éliminer les petits points et épaissir les traits
  3. Seuil de l'image
  4. Remplir du sol, en partant du bon point
  5. Inverser le remplissage d'inondation
  6. Trouvez des contours et tracez-en un à la fois, à peu près dans la zone Du rectangle. Pour mon image redimensionnée (500x500), je mets une zone de contour de Dans une plage de 500 à 2500 (essais et erreurs malgré tout).
  7. Recherchez un rectangle de délimitation et rognez ce masque à partir de l'image principale.
  8. Puis enregistrez cette pièce avec son nom propre - ce que je n'ai pas fait.

    Peut-être, il y a un moyen plus simple, mais j'ai aimé ça. Ne pas mettre le code parce que Je l'ai fait tout maladroit. Va mettre si tu en as encore besoin.

    Voici à quoi ressemble le masque lorsque vous trouvez des contours à la fois

 enter image description here

code:

import cv2;
import numpy as np;

# Run the code with the image name, keep pressing space bar

# Change the kernel, iterations, Contour Area, position accordingly
# These values work for your present image

img = cv2.imread("your_image.jpg", 0);
h, w = img.shape[:2]
kernel = np.ones((15,15),np.uint8)

e = cv2.erode(img,kernel,iterations = 2)  
d = cv2.dilate(e,kernel,iterations = 1)
ret, th = cv2.threshold(d, 150, 255, cv2.THRESH_BINARY_INV)

mask = np.zeros((h+2, w+2), np.uint8)
cv2.floodFill(th, mask, (200,200), 255); # position = (200,200)
out = cv2.bitwise_not(th)
out= cv2.dilate(out,kernel,iterations = 3)
cnt, h = cv2.findContours(out,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(cnt)):
            area = cv2.contourArea(cnt[i])
            if(area>10000 and area<100000):
                  mask = np.zeros_like(img)
                  cv2.drawContours(mask, cnt, i, 255, -1)
                  x,y,w,h = cv2.boundingRect(cnt[i])
                  crop= img[ y:h+y,x:w+x]
                  cv2.imshow("snip",crop )
                  if(cv2.waitKey(0))==27:break

cv2.destroyAllWindows()
3
I.Newton
_, contours, hierarchy = cv2.findContours(edged, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

vous utilisez cv2.RETR_LIST pour rechercher des contours dans l'image. Pour que votre image obtienne une meilleure sortie, utilisez cv2.RETR_EXTERNAL . Avant d'utiliser cette première supprimez noir bordure ligne de l'image. 

cv2.RETR_LIST vous donne la liste de tous les contours pour l'image

cv2.RETR_EXTERNAL ne vous donne que des contours externes ou externes, pas des contours internes

changer de ligne en 

 _, contours, hierarchy = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

Hiérarchie des contours

0
Kallz