简体   繁体   中英

OpenCV: Contours hidden behind mask. How to detect when a contour is about to move near mask edge?

Summary of Question

I am detecting object silhouettes in front of a light source. To simplify the background and remove noise, I require masking everything that isn't the light source. How can I tell when the object would be on the edge of the masked area?

Assumptions

Assume featureless (monochrome black and white for edge detection) and ambiguous (a square in image 1 may be a circle in image 2) in shape.

Detailed Explanation of the Problem with "High Quality" Figures

Consider a silhouette in front of a light source. It is distinct and we can tell it is nested within the outer contour. Figure 1 depicts a simplified case.

独特的轮廓

We can treat our outer circle as a mask in this case, and easily ignore everything NOT within the contour. Figure 2 depicts the simplified case with some edge detection.

这里的轮廓很简单。好哇。

Everything works lovely until the silhouette moves to the edge of the light source. Suddenly we run into problems. Figure 3 is an example of a shape on the edge.

剪影与面具无法区分。

The silhouette is indistinguishable from the black of the background/masked area. OpenCV either assumes that suddenly the contour of our light source is funny shaped and there is no other object to be detected.

The Question Restated

What tools can I use to detect that there has been some sort of interruption of the edge shape? Is there a good/computational cheap way of determining if our silhouette is intersecting with another?

Graveyard of What I Know Does NOT Work

  • Assuming a static or simple silhouette shape. The figures are cartoons representing a more complicated real problem.
  • Assuming a perfectly round light source. HoughCircles does not work.

You can use the cv2.log_polar function to unwrap the circle/oval shape.

log_polar

After that, np.argmax can be used to find the curve. Try smoothing out the curve using Scipy's signal.savgol_filter() . When the object blocks the light source, there will be a big difference between the smoothed line and the argmax data: 图形

This is the code that I used:

import numpy as np
import cv2
# Read the image
img = cv2.imread('/home/stephen/Desktop/JkgJw.png', 0)
# Find the log_polar image
log_polar = cv2.logPolar(img, (img.shape[0]/2, img.shape[1]/2), 40, cv2.WARP_FILL_OUTLIERS)
# Create a background to draw on
bg = np.zeros_like(log_polar)
# Iterate through each row in the image and get the points on the edge
h,w = img.shape
points = []
for col in range(h-1):
    col_slice = log_polar[col:col+1, :]
    curve = np.argmax(255-col_slice)
    cv2.circle(bg, (curve, col), 0, 255, 1)
    points.append((curve, col))

cv2.imshow('log_polar', log_polar)
cv2.waitKey(0)
cv2.destroyAllWindows()


import scipy
from scipy import signal

x,y = zip(*points)
x_smooth = signal.savgol_filter(x,123,2)

import matplotlib.pyplot as plt
plt.plot(x)
plt.plot(x_smooth)
plt.show()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM