Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Edge detection on colored background using OpenCV

I am using following code to detect edges from given document.

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;
}

And then I can find the document from this edges by finding largest contour from this.

My problem is I can find the document from following pic:

enter image description here

but not from following pic:

enter image description here

How can I improve this edge detection?

like image 820
Gunaseelan Avatar asked Dec 20 '17 05:12

Gunaseelan


People also ask

Can OpenCV detect colors?

OpenCV has some built-in functions to perform Color detection and Segmentation operations. So what are Color Detection and Segmentation Techniques in Image Processing? Color detection is a technique of detecting any color in a given range of HSV (hue saturation value) color space.

What is used to OpenCV is used to detect edges of the image?

Canny Edge Detection is used to detect the edges in an image. It accepts a gray scale image as input and it uses a multistage algorithm. You can perform this operation on an image using the Canny() method of the imgproc class, following is the syntax of this method.

How do we detect edges of items in a drawing in OpenCV?

Sobel Edge Detection is one of the most widely used algorithms for edge detection. The Sobel Operator detects edges that are marked by sudden changes in pixel intensity, as shown in the figure below. The rise in intensity is even more evident, when we plot the first derivative of the intensity function.

What is color edge detection?

in color images. Edge detection is one of the most important tasks in image processing and scene analysis systems. It denotes the procedure of detecting meaningful discontinuities (edges) of the image function (see Figure 1 for an example of edge detection in color and gray-level image).


2 Answers

I use Python, but the main idea is the same.

If you directly do cvtColor: bgr -> gray for img2, then you must fail. Because the gray becames difficulty to distinguish the regions:

enter image description here


Related answers:

  1. How to detect colored patches in an image using OpenCV?
  2. Edge detection on colored background using OpenCV
  3. OpenCV C++/Obj-C: Detecting a sheet of paper / Square Detection

In your image, the paper is white, while the background is colored. So, it's better to detect the paper is Saturation(饱和度) channel in HSV color space. For HSV, refer to https://en.wikipedia.org/wiki/HSL_and_HSV#Saturation.


Main steps:

  1. Read into BGR
  2. Convert the image from bgr to hsv space
  3. Threshold the S channel
  4. Then find the max external contour(or do Canny, or HoughLines as you like, I choose findContours), approx to get the corners.

This is the first result:

enter image description here

This is the second result:

enter image description here

The Python code(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)[-2]
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)
like image 172
Kinght 金 Avatar answered Oct 16 '22 04:10

Kinght 金


In OpenCV there is function called dilate this will darker the lines. so try the code like below.

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;
}
like image 35
Bill Karwin Avatar answered Oct 16 '22 05:10

Bill Karwin