python - 检测图像中的水平线

标签 python image opencv python-imaging-library

问题:
我正在处理一个包含许多看起来像这样的图像的数据集:

img2
img1

现在我需要将所有这些图像水平或垂直定向,以便调色板位于图像的底部或右侧。这可以通过简单地旋转图像来完成,但棘手的部分是弄清楚哪些图像应该旋转,哪些不应该旋转。

我试过的:

我认为最好的方法是检测将调色板与图像分开的白线。我决定旋转底部带有调色板的所有图像,使其位于右侧。

# yes I am mixing between PIL and opencv (I like the PIL resizing more)
# resize image to be 128 by 128 pixels
img = img.resize((128, 128), PIL.Image.BILINEAR)
img = np.array(img)

# perform edge detection, not sure if these are the best parameters for Canny
edges = cv2.Canny(img, 30, 50, 3, apertureSize=3)

has_line = 0

# take numpy slice of the area where the white line usually is 
# (not always exactly in the same spot which probably has to do with the way I resize my image) 
for line in edges[75:80]:

    # check if most of one of the lines contains white pixels
    counts = np.bincount(line)
    if np.argmax(counts) == 255:
        has_line = True

# rotate if we found such a line
if has_line == True:
    s = np.rot90(s)


它正常工作的一个例子:

enter image description here

它工作不正确的一个例子:

enter image description here

这可能适用于 98% 的图像,但在某些情况下,它会旋转不应旋转的图像或不旋转应旋转的图像。也许有一种更简单的方法可以做到这一点,或者可能有一种更精细、更一致的方法?我可以手动完成,但我正在处理很多图像。感谢您的任何帮助和/或评论。

以下是我的代码无法用于测试目的的一些图像:

enter image description here
enter image description here

最佳答案

您可以通过设置一个非常高的阈值(例如 250)来对图像进行阈值处理,以利用您的线条是白色的属性。这将使所有背景变黑。现在创建一个特殊的水平内核,形状类似于 (1, 15)并用它侵 eclipse 你的形象。这将做的是从图像中删除垂直线,只留下水平线。

import cv2
import numpy as np

img = cv2.imread('horizontal2.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 250, 255, cv2.THRESH_BINARY)

kernel_hor = np.ones((1, 15), dtype=np.uint8)
erode = cv2.erode(thresh, kernel_hor)

thresh eroded

正如问题中所述,色觉只能在右侧或底部。因此,我们可以测试以检查正确区域有多少轮廓。为此,只需将图像分成两半并取正确的部分。在找到轮廓之前,先扩大结果以使用法线 (3, 3) 填充任何间隙。核心。使用 cv2.RETR_EXTERNAL找到轮廓并计算我们找到了多少,如果大于某个数字,则图像正面朝上是正确的,无需旋转。
right = erode[:, erode.shape[1]//2:]

kernel = np.ones((3, 3), dtype=np.uint8)
right = cv2.dilate(right, kernel)

cnts, _ = cv2.findContours(right, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if len(cnts) > 3:
    print('No need to rotate')
else:
    print('rotate')
    #ADD YOUR ROTATE CODE HERE

附言我对您提供的所有四张图片进行了测试,效果很好。如果它不适用于任何图像,请告诉我。

关于python - 检测图像中的水平线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61893048/

相关文章:

python - 如何用一个循环依次遍历多个列表?

image - 用于获取当前登录用户的个人资料图片的 Meteor 快捷方式,无论平台如何

html - 图像悬停导致显示一些文本

java - 将从网络摄像头获取的图像添加到现有的 JPanel

python - 在 ubuntu 16.04 上安装 opencv 后出现错误 no module opencv

python - 将 CSV 列内容拆分为多列

python - 解压的值太多,python,findcontours

python - 如何从 app.callback 返回数据帧,并将我的输出作为 dbc.Table.from_dataframe

Python flask ajax 获取图像 - 最后编辑是问题

c++ - 比较两个矩阵Opencv的面积