Python中如何使用OpenCV去除图片底部的横线?

低端有一条很小的蓝线请问如何去掉?
这个是原图请问如何去出掉低端的横线。
Python中如何使用OpenCV去除图片底部的横线?
直接用 PIL 不行吗
import cv2
import numpy as np
def remove_bottom_lines(image_path, output_path, line_thickness=2, margin=10):
"""
去除图片底部的横线
参数:
image_path: 输入图片路径
output_path: 输出图片路径
line_thickness: 检测线条的厚度阈值
margin: 从底部开始检测的区域高度
"""
# 读取图片
img = cv2.imread(image_path)
if img is None:
raise ValueError("无法读取图片,请检查路径")
# 转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 获取图片尺寸
height, width = gray.shape
# 提取底部区域(最后margin行)
bottom_region = gray[height - margin:, :]
# 使用Canny边缘检测
edges = cv2.Canny(bottom_region, 50, 150, apertureSize=3)
# 使用霍夫变换检测直线
lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=50,
minLineLength=width*0.3, maxLineGap=10)
# 如果没有检测到直线,直接保存原图
if lines is None:
cv2.imwrite(output_path, img)
print("未检测到横线")
return img
# 创建掩码
mask = np.ones_like(img) * 255
# 标记检测到的横线区域
for line in lines:
x1, y1, x2, y2 = line[0]
# 将局部坐标转换为全局坐标
y1 += height - margin
y2 += height - margin
# 计算线条角度(只处理接近水平的线)
angle = np.abs(np.arctan2(y2 - y1, x2 - x1) * 180 / np.pi)
if angle < 10 or angle > 170: # 接近水平线
# 扩展线条区域
y_center = (y1 + y2) // 2
top = max(0, y_center - line_thickness)
bottom = min(height, y_center + line_thickness)
mask[top:bottom, :] = 0
# 使用inpainting修复被标记的区域
mask_gray = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
result = cv2.inpaint(img, mask_gray, inpaintRadius=3, flags=cv2.INPAINT_TELEA)
# 保存结果
cv2.imwrite(output_path, result)
return result
# 使用示例
if __name__ == "__main__":
input_img = "input.jpg" # 你的输入图片
output_img = "output.jpg" # 输出图片
try:
result = remove_bottom_lines(input_img, output_img, margin=20)
print(f"处理完成,结果已保存到 {output_img}")
except Exception as e:
print(f"处理失败: {e}")
核心思路:
- 用Canny检测底部边缘
- 用霍夫变换找横线
- 创建掩码标记线条区域
- 用inpainting智能填充
参数调整建议:
margin:根据横线位置调整检测区域高度line_thickness:根据线条粗细调整minLineLength:调整检测线条的最小长度
一句话建议: 先用小margin值试效果,再逐步调整参数。
mask
height 高于某个定值,如果 RGB 颜色不是白色,填充这个像素为白色,收工
数数那是多少像素,然后 rect,把上面的部分截取出来,或者直接把下面的全部写成相同像素
如果图片只有这条横线,而且一定是最底端,图片都这么大,那么你直接把最底端的像素的颜色都设置成背景颜色就好了
如果这条横线还会在其他地方,你可以用 HoughLineP (设置 threshold 和 minLineLength 俩参数),找最长的那条直线,因为斜率一定是 0,所以 HoughLineP 对应的第一个点的纵坐标就是直线的那个位置
是这样的, 主要有多个图片, 这个只是一个个例, 而且高度多少不一定, 可能多点, 可能少点, 三楼的方法 ok 但是感觉代码还是写的有点死, ok 我先试下谢谢。
5 楼哈夫变换线识别可解,简单点的话就遍历一遍就行了
opencv 运行下面代码,可以看到如图
http://image.xujialiang.net/[email protected]
很容易看出从第一行开始切割。。
import cv2
import numpy as np
import matplotlib.pyplot as plt
ori_img = cv2.imread(’./TestData/’ + ‘111.png’)
im_gray = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
im_at_mean = cv2.adaptiveThreshold(im_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 10)
cv2.imshow(‘im_at_mean’ , im_at_mean)
im_at_mean_inv = cv2.bitwise_not(im_at_mean)
horizontal_sum = np.sum(im_at_mean_inv, axis=1)
plt.plot(horizontal_sum, range(horizontal_sum.shape[0]))
plt.gca().invert_yaxis()
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
上面打错一个字。。。很容易看出从第几行开始切割。。
可以统计每行的 RGB 色彩的数量,如果某一行同一颜色的数据和列数差不多(可以设置个阈值),就可以把这行看做是一条横线,直接切掉或者修改这行颜色即可。
不用 opencv 也行的。
读取一下像素值。大于多少高度(避免把字给处理了),颜色值低于 255(阈值自己设置)的都置位 255

