【问题标题】:Can I distinguish between a square and a lozenge with contour in OpenCV我可以在OpenCV中区分正方形和带有轮廓的菱形吗
【发布时间】:2017-03-25 21:17:54
【问题描述】:

我想用 opencv 和 python 检测表单 所以我选择了轮廓特征,但现在我有问题如何使用 opencv 和 python 区分正方形和菱形 如果有其他方法你能告诉我请我的图片是这样的:enter image description here 我添加我的代码

#-*- coding: utf-8 -*-

import cv2
import numpy as np
from pyimagesearch.shapedetector import ShapeDetector
import argparse
import imutils
from scipy import ndimage
import math
import matplotlib.pyplot as plt
from skimage import io, morphology, img_as_bool, segmentation
global limit
 # cv2.threshold(src, thresh, maxval, type[, dst])

import math
def angle(pt1, pt2):
    x1, y1 = pt1
    x2, y2 = pt2
    inner_product = x1*x2 + y1*y2
    len1 = math.hypot(x1, y1)
    len2 = math.hypot(x2, y2)
    return math.acos(inner_product/(len1*len2))

def calculate(pt, ls):
    i = 2
    for x in ls:
        pt2 = (x, i)
        i = i+1
        ang = angle(pt, pt2)*180/math.pi
        ang = ang * (-1)
        print (ang)
Image = cv2.imread("114.png")

# Extraction of Blue channel
b = Image[:,:,0]

# Callback Function for Trackbar (but do not any work)
def nothing(*arg):
    pass

 # Generate trackbar Window Name
TrackbarName = "Trackbar"

 # Make Window and Trackbar
cv2.namedWindow("window", cv2.WINDOW_NORMAL)
cv2.createTrackbar(TrackbarName, "window", 0, 250, nothing)

img_threshed = np.zeros(b.shape, np.uint8)



ret,img_threshed = cv2.threshold(b,168,255,cv2.THRESH_BINARY)
cv2.imshow("window55", img_threshed)
# Expanding borders of the objects
kernel = np.ones((9, 9),np.uint8)
img_dilated = cv2.dilate(img_threshed, kernel)
cv2.namedWindow("Dilated Blue Channel", cv2.WINDOW_NORMAL)
cv2.imshow("Dilated Blue Channel", img_dilated)


# Retrieving contours by subtraction base objects from the expanded objects
img_contours = img_dilated - img_threshed
cv2.namedWindow("Contours", cv2.WINDOW_NORMAL)
cv2.imshow("Contours", img_contours)

median = cv2.medianBlur(img_contours,3)
cv2.imshow("median img_threshed", median)
#_, contours0, hierarchy = cv2.findContours( median, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#cnts = [cv2.approxPolyDP(cnt, 2, True) for cnt in contours0]



gray = cv2.imread('114.png')
    #gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (3, 3), 0)

    # apply Canny edge detection using a wide threshold, tight
    # threshold, and automatically determined threshold
wide = cv2.Canny(blurred, 90, 150)
cnts = cv2.findContours(img_contours, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)

#----Find contour in the image----
_, contours, hierarchy = cv2.findContours(img_contours, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)




cnts = cnts[0] if imutils.is_cv2() else cnts[1]
    # loop over the contours
for c in cnts:



        #----Draw a rectangle having minimum area around it using Contour features as you mentioned----
        rect = cv2.minAreaRect(c)  #---I used cnt[0] since there is only one contour in the image----
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        im = cv2.drawContours(Image, [box], 0, (0,0,255), 2)

        #----Draw one diagonal ----
        #cv2.line(Image,(box[2][0],box[2][1]),(box[0][0],box[0][1]), (255,0,0),2)
        #cv2.line(Image,(0,10),(Image.shape[1], 10), (255,255,0),2)
        #calculate(cv2.line(Image,(box[2][0],box[2][1]),(box[0][0],box[0][1]), (255,0,0),2),cv2.line(Image,(0,10),(Image.shape[1], 10), (255,255,0),2))


cv2.imwrite("Final_Image.jpg", Image)
    # show the output image
cv2.imshow("Image", Image)
cv2.waitKey(0)

cv2.destroyAllWindows()

【问题讨论】:

  • 你必须玩正方形的对角线和菱形的对角线

标签: python opencv image-processing contour


【解决方案1】:

如 cmets 部分所述,如果您想区分明显的正方形和菱形,唯一不同的属性是对角线。

在 OpenCV 中使用 python 我编写了以下代码以获得正方形和菱形的 1 个对角线:

#----Find contour in the image----
_, contours, hierarchy = cv2.findContours(th, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

#----Draw a rectangle having minimum area around it using Contour features as you mentioned----
rect = cv2.minAreaRect(cnt[0])  #---I used cnt[0] since there is only one contour in the image----
box = cv2.boxPoints(rect)
box = np.int0(box)
im = cv2.drawContours(im1, [box], 0, (0,0,255), 2)

#----Draw one diagonal ----
cv2.line(im1,(box[2][0],box[2][1]),(box[0][0],box[0][1]), (255,0,0),2)

cv2.imwrite("Final_Image.jpg", im1)

这是我得到的:

广场:

菱形:

既然你已经获得了对角线,你必须将它与参考线进行比较以找到角度,以确定它是否是正方形。

首先画一条参考线(我认为是水平线)

cv2.line(im1,(0,10),(im1.shape[1], 10), (255,255,0),2)

你会得到:

广场:

菱形:

现在你只需要计算这两条线之间的角度(对角线和参考线):

  1. 如果角度是 90 度或 0 => 菱形。

  2. 否则 => 正方形

如何计算两条线之间的角度?

THIS POST

【讨论】:

  • 谢谢@Jeru Luke,但是我怎样才能明白这 2 行扫描的重点,请给我更多信息?
  • 我在我的问题中添加了一张照片,你看到了吗?
  • 您已经添加了图像,但我在 18 小时前回答了问题!!!您可以将相同的技术应用于您的图像
  • 是的,我编辑了我的问题,但是我怎样才能得到这两行的要点,因为在这个link 我看到使用一个点和一个向量没有?
  • cv2.line(im1,(box[2][0],box[2][1]),(box[0][0],box[0][1]), (255,0,0),2) 具有对角线的点。参考线的点在cv2.line(im1,(0,10),(im1.shape[1], 10), (255,255,0),2)
猜你喜欢
  • 1970-01-01
  • 2019-08-17
  • 1970-01-01
  • 2012-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-20
  • 2019-02-20
相关资源
最近更新 更多