python - 检测图像中的正方形(绘画)并使用 python 在它们周围绘制轮廓

标签 python opencv image-processing computer-vision detection

我正在尝试在每幅画上检测并绘制一个矩形轮廓,例如这张图片:

我遵循了一些指南并执行了以下操作:

  1. 灰度转换
  2. 应用中值模糊
  3. 锐化图像
  4. 应用自适应阈值
  5. 应用形态梯度
  6. 寻找轮廓
  7. 绘制轮廓

得到如下结果:

我知道这很乱,但有没有办法以某种方式更好地检测和绘制画作周围的轮廓?

这是我使用的代码:

path = '<PATH TO THE PICTURE>'

#reading in and showing original image
image = cv2.imread(path)
image = cv2.resize(image,(880,600)) # resize was nessecary because of the large images
cv2.imshow("original", image)
cv2.waitKey(0)
cv2.destroyAllWindows() 

# grayscale conversion
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("painting_gray", gray)
cv2.waitKey(0)
cv2.destroyAllWindows() 

# we need to find a way to detect the edges better so we implement a couple of things
# A little help was found on stackoverflow: https://stackoverflow.com/questions/55169645/square-detection-in-image 
median = cv2.medianBlur(gray,5)
cv2.imshow("painting_median_blur", median) #we use median blur to smooth the image
cv2.waitKey(0)
cv2.destroyAllWindows() 

# now we sharpen the image with help of following URL: https://www.analyticsvidhya.com/blog/2021/08/sharpening-an-image-using-opencv-library-in-python/ 
kernel = np.array([[0, -1, 0],
                [-1, 5,-1],
                [0, -1, 0]])
image_sharp = cv2.filter2D(src=median, ddepth=-1, kernel=kernel)
cv2.imshow('painting_sharpend', image_sharp)
cv2.waitKey(0)
cv2.destroyAllWindows()

# now we apply adapptive thresholding
# thresholding: https://opencv24-python-tutorials.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_thresholding/py_thresholding.html#adaptive-thresholding 
thresh = cv2.adaptiveThreshold(src=image_sharp,maxValue=255,adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                            thresholdType=cv2.THRESH_BINARY,blockSize=61,C=20)   
cv2.imshow('thresholded image', thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()

# lets apply a morphological transformation
kernel = np.ones((7,7),np.uint8)
gradient = cv2.morphologyEx(thresh, cv2.MORPH_GRADIENT, kernel)
cv2.imshow('dilated image', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()



# # lets now find the contours of the image
# # find contours: https://docs.opencv.org/4.x/dd/d49/tutorial_py_contour_features.html
contours, hierarchy = cv2.findContours(gradient, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print("contours: ", len(contours))
print("hierachy: ", len(hierarchy))
print(hierarchy)


cv2.drawContours(image, contours, -1, (0,255,0), 3)
cv2.imshow("contour image", image)
cv2.waitKey(0)
cv2.destroyAllWindows() 

感谢提示、帮助或代码!

最佳答案

这里有一个简单的方法:

  1. 获取二值图像。我们load the image , grayscale , Gaussian blur , 然后 Otsu's threshold获取二值图像。

  2. 两次通过扩张合并轮廓。此时,我们有一个二值图像,但单独分离轮廓。由于我们可以假设一幅画是一个单一的大方形轮廓,我们可以将小的单独的相邻轮廓合并在一起形成一个单一的轮廓。为此,我们使用 cv2.getStructuringElement 创建了一个垂直和水平内核。然后 dilate将它们合并在一起。根据图像,您可能需要调整内核大小或膨胀迭代次数。

  3. 检测绘画。现在我们 find contours并使用 contour area 进行过滤使用最小阈值区域来过滤掉小轮廓。最后我们得到了bounding rectangle坐标并用 cv2.rectangle 绘制矩形.


enter image description here

代码

import cv2

# Load image, grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread('1.jpeg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (13,13), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Two pass dilate with horizontal and vertical kernel
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,5))
dilate = cv2.dilate(thresh, horizontal_kernel, iterations=2)
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,9))
dilate = cv2.dilate(dilate, vertical_kernel, iterations=2)

# Find contours, filter using contour threshold area, and draw rectangle
cnts = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area > 20000:
        x,y,w,h = cv2.boundingRect(c)
        cv2.rectangle(image, (x, y), (x + w, y + h), (36, 255, 12), 3)

cv2.imshow('thresh', thresh)
cv2.imshow('dilate', dilate)
cv2.imshow('image', image)
cv2.waitKey()

关于python - 检测图像中的正方形(绘画)并使用 python 在它们周围绘制轮廓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71739517/

相关文章:

javascript - Canvas 旋转、toDataUrl,然后裁剪会破坏图像质量

python - 如何在Python中用其区域指定的颜色填充openCV轮廓?

python - PyQT:如何打开新窗口

python - 视频帧变化检测

python - 查找穿过质心的每个线段的长度,以及如何将线收缩到外部轮廓

image-processing - 颜色配置文件在图形程序中的作用

python - 安装 askbot 后 Django 应用程序未运行

python - 用于 MySQL 的 Peewee ORM JSONField

Python sympy 方程矩阵

c++ - 如何使用 Chrono 和 OpenCV 计算实时视频流的 FPS?