-2

i'm trying to detect contour for ID card but it never work; I tried with the four_point_transform, boundingrect,boundries,active_contours,hough transform and also the same result , the contour with be used to scan just the id card . the id looks like that : here This is how the code looks like:

 from trans import four_point_transform
from skimage.filters import threshold_local
import numpy as np
import cv2
import imutils

def edgeDetection(image):        
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    gray = cv2.GaussianBlur(image, (5, 5), 0)
    edged = cv2.Canny(gray, 200,150 )
    return edged

def detectrectarrondi(image,edged):        
    orig = image.copy()
    gray = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
    edged = cv2.Canny(gray, 50, 40)
    orig_edged = edged.copy()

    (_,contours, _) = cv2.findContours(orig_edged, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
    contours = sorted(contours, key=cv2.contourArea, reverse=True)

    for contour in contours:
        c = max(contours, key = cv2.contourArea)
        (x,y,w,h) = cv2.boundingRect(c)
        screen = cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2)
        return screen              

def scan(screen,image):
    ratio = image.shape[0] / 500.0
    warped = four_point_transform(image, screen.reshape(4, 2) * ratio)
    warped= cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
    T = threshold_local(warped, 11, offset = 10, method = "gaussian")
    warped = (warped > T).astype("uint8") * 255

    return warped  
BADS
  • 141
  • 8

1 Answers1

1

As I can't write a comment because I don't have 50 reputations, I will give you some steps to follow here: 1/ Convert your image to gray scale using cvtColor.

2/ Apply GaussianBlur to reduce noise.

3/ Apply Canny edge detector, you need to play with lower and higher threshold values to get the best result

4/ This step is not needed but can be helpful, apply a morphological operation to close incomplete contours using MORPH_CLOSE parameter.

5/ Find your contours using findContours

6/ Loop through the found contours and draw the bonding rectangle that have the biggest area.

I hope this help you, tell me if you want to see some code.

EDIT:

   Imgproc.cvtColor(origMat, mGray, Imgproc.COLOR_BGR2GRAY);

    Imgproc.GaussianBlur(mGray, mGray, new Size(5, 5), 5);

    Imgproc.Canny(mGray, mGray, 30, 80, 3, false);

    Mat kernell = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(9,9));

    Imgproc.morphologyEx(mGray, mGray, Imgproc.MORPH_CLOSE, kernell);

    Imgproc.dilate(mGray, mGray, Imgproc.getStructuringElement(Imgproc.MORPH_CROSS, new Size(3, 3)));


    List<MatOfPoint> contours = new ArrayList<MatOfPoint>();

    Mat hierarchy = new Mat();

    Imgproc.findContours(mGray, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

    MatOfPoint2f approxCurve = new MatOfPoint2f();

    double largest_area=0;
    int largest_contour_index=0;
    Rect rect = new Rect();

    for (int idx = 0; idx < contours.size() ; idx++) {

        double a = Imgproc.contourArea(contours.get(idx));  //Find the area of contour

        if (a > largest_area) {
            largest_area = a;
            largest_contour_index = idx;
            rect = Imgproc.boundingRect(contours.get(idx));
        }
    }
        Imgproc.rectangle(origMat, rect.tl(), rect.br(), new Scalar(0, 255, 0));

    return origMat;

You can have a look at this good answer to set Canny theshold values automatically using the median value of your image

https://stackoverflow.com/a/41895229

Amine
  • 2,241
  • 2
  • 19
  • 41
  • yes i'd like to see some code ; i put also my code in the answers block ! – BADS Feb 28 '19 at 11:03
  • See the edit , this code is in java but it wouldn't be difficult to convert in python, later I will add the code to extract that largest contour to a new Mat object. – Amine Feb 28 '19 at 13:28