user972014
user972014

Reputation: 3856

Find the corner of a projected rectangle of a single color in numpy

I have an image of a rectangle, which is projected. The entire rectangle is colored with a single plain color. Similar to this image:

enter image description here

I'm trying to find the 4 corners of it an efficiently, probably using numpy and cv2

Upvotes: 0

Views: 661

Answers (2)

user972014
user972014

Reputation: 3856

The code I eventually used was this:

# image is the original image, color is the polygon's color as BGR
width = image.shape[1]
height = image.shape[0]
coords = np.argwhere(np.ones([height, width]))
coords_x = coords[:, 1]
coords_y = coords[:, 0]

r,g,b = image[:,:,2], image[:,:,1], image[:,:,0]
color_mask = (r[coords_y, coords_x] == color[2]) & (g[coords_y, coords_x] == color[1]) & (b[coords_y, coords_x] == color[0])            
coords_x_filtered = np.extract(color_mask, coords_x)
coords_y_filtered = np.extract(color_mask, coords_y)
max_br = np.argmax(coords_x_filtered + coords_y_filtered)  # Find the pixel furthest along y=x direction
max_tr = np.argmax(coords_x_filtered - coords_y_filtered)   # ...
max_tl = np.argmax(-coords_x_filtered - coords_y_filtered)
max_bl = np.argmax(-coords_x_filtered + coords_y_filtered)

x, y = int(coords_x_filtered[max_tl]), int(coords_y_filtered[max_tl])
# Continue to other corners

The point is to find the pixel that is furthest along a direction, for the 4 directions. It does require you to define what is "furthest" specifically I use the y=x and y=-x directions, which is not perfect, but good enough

Upvotes: 0

Fred Guth
Fred Guth

Reputation: 1667

If the polygons were rectangles, you could only use numpy.where, but they are quadrilaterals and I don't know a way to do that just with numpy.

Here is a way to do this (I saved your image as greens.png):

import cv2
import numpy as np


# load image
img = cv2.imread("greens.png")
h,w,c  = img.shape

mask = img.copy()
mask[:,:,:]=0
mask[np.where((img[:, :,0] == 73) & (img[:, :,1] == 239) & (img[:, :, 2] == 110))] = 255
mask = np.float32(mask[:,:,0])
dst = cv2.cornerHarris(mask, 3, 3, 0.07)
img[dst > 0.07*dst.max()] = [0, 0, 255]
extremes = np.where(dst > 0.07*dst.max())
for i in range(len(extremes[0])):
  print (extremes[0][i], extremes[1][i])
while True:
  cv2.imshow('img', img)
  if cv2.waitKey(10) & 0xFF == ord('q'):
        break
cv2.destroyAllWindows()

I am not sure if Harris is the fastest corner detection. I have seen opencv has a FastFeatureDetection but I have never used it.

Upvotes: 2

Related Questions