1

Lets say I have the following image where there is a folder image with a white label on it. What I want is to detect the coordinates of end points of the folder and the white paper on it (both rectangles). Using the coordinates, I want to know the exact place of the paper on the folder.

GIVEN : The inner white paper rectangle is always going to be of the fixed size, so may be we can use this knowledge somewhere?

I am new to opencv and trying to find some guidance around how should I approach this problem?

Problem Statement : We cannot rely on color based solution since this is just an example and color of both the folder as well as the rectangular paper can change. There can be other noisy papers too but one thing is given, The overall folder and the big rectangular paper would always be the biggest two rectangles at any given time.

I have tried opencv canny for edge detection and it looks like this image.

Now how can I find the coordinates of outer rectangle and inner rectangle.

Image

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
Scorpion
  • 633
  • 3
  • 11
  • 24

3 Answers3

1

This solution helps to identify the white paper region of the image. This is the full code for the solution:

import cv2
import numpy as np
image = cv2.imread('stack2.jpg',-1)
paper = cv2.resize(image,(500,500))
ret, thresh_gray = cv2.threshold(cv2.cvtColor(paper, cv2.COLOR_BGR2GRAY),
                        200, 255, cv2.THRESH_BINARY)
image, contours, hier = cv2.findContours(thresh_gray, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
for c in contours:
    area = cv2.contourArea(c)
    rect = cv2.minAreaRect(c)
    box = cv2.boxPoints(rect)
    # convert all coordinates floating point values to int
    box = np.int0(box)
    # draw a green 'nghien' rectangle
    if area>500:
        cv2.drawContours(paper, [box], 0, (0, 255, 0),1)
        print([box])
cv2.imshow('paper', paper)
cv2.imwrite('paper.jpg',paper)
cv2.waitKey(0)

First using a manual threshold(200) you can detect paper in the image.

ret, thresh_gray = cv2.threshold(cv2.cvtColor(paper, cv2.COLOR_BGR2GRAY), 200, 255, cv2.THRESH_BINARY)          

After that you should find contours and get the minAreaRect(). Then you should get coordinates for that rectangle(box) and draw it.

rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(paper, [box], 0, (0, 255, 0),1)

In order to avoid small white regions of the image you can use area = cv2.contourArea(c) and check if area>500 and drawContours().

final output:

Console output gives coordinates for the white paper.

console output:

[array([[438, 267],
       [199, 256],
       [209,  60],
       [447,  71]], dtype=int64)]
Ishara Madhawa
  • 3,549
  • 5
  • 24
  • 42
  • Just updated the question, we cannot rely on any color based solution. Can we take help of edge detection solutions to detect the biggest two rectangles like using Canny? – Scorpion Jun 13 '18 at 06:11
  • I like your idea of using area concept since (just updated), the inner label/sticker is always going to be of fixed size, so may be we can use that knowledge. – Scorpion Jun 13 '18 at 20:50
  • I tried your code and tweaked the settings to detect the white label on my side, But the problem statement is to get the coordinates of the folder as well as the label so that we can know exactly where the label is on the folder, Detecting the label if just one part of the problem – Scorpion Jun 13 '18 at 21:05
  • I updated the answer. Now you can get the coordinates of the label. – Ishara Madhawa Jun 16 '18 at 08:15
1

For this image, there are three domain colors: (1) the background-yellow (2) the folder-blue (3) the paper-white. Use the color info may help, I analysis it in RGB and HSV like this:

enter image description here

As you can see(the second row, the third cell), the regions can be easily seperated in H(HSV) if you find the folder mask first.

We can choose

My steps:

(1) find the folder region mask in HSV using inRange(hsv, (80, 10, 20), (150, 255, 255))

(2) find contours on the mask and filter them by width and height

Here is the result:

enter image description here


Related:

Choosing the correct upper and lower HSV boundaries for color detection with`cv::inRange` (OpenCV)

How to define a threshold value to detect only green colour objects in an image :Opencv

Community
  • 1
  • 1
Kinght 金
  • 17,681
  • 4
  • 60
  • 74
1

You can opt for (Adaptive Threshold)[https://docs.opencv.org/3.4/d7/d4d/tutorial_py_thresholding.html]

  1. Obtain the hue channel of the image.

enter image description here

  1. Perform adaptive threshold with a certain block size. I used size of 15 for half the size of the image.

enter image description here

This is invariant to color as you expected. Now you can go ahead and extract what you need!!

Jeru Luke
  • 20,118
  • 13
  • 80
  • 87
  • Got the hue channel and when am trying to perform adaptive threshold, am getting weird error. Code : th2 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,\ cv.THRESH_BINARY,15,2) Exception : OpenCV(3.4.1) Error: Assertion failed (src.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3))) in adaptiveThreshold, file /Users/travis/build/skvark/opencv-python/opencv/modules/imgproc/src/thresh.cpp cv2.error: OpenCV(3.4.1) /thresh.cpp:1524: error: (-215) src.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) in function adaptiveThreshold – Scorpion Jun 13 '18 at 21:41
  • Got it working :), My next problem statement is that given the inner label of fixed size (if this info is useful to avoid other small label noises), I need to find the coordinate of outer box and inner box so that I can locate exact position of the label on folder. – Scorpion Jun 13 '18 at 21:50