python opencv:批量识别拼接图片分界线并进行自动裁剪
本文主要内容
- 一 项目概要
- 二 项目流程
- 三 图像边缘提取
- 四 直线检测
- 五 项目代码
一 项目概要
在网上找图片素材时,有很多的图片是长图片,在一张图片上拼接了许多张图片,而很多时候我们需要单张图片,此时就需要将长图进行裁剪,一般可以用图片工具进行简单裁剪,高级点可以采用ps进行切片处理,如果图片数量少还好说一旦有大量的图片需要裁剪就很繁琐并且费时费力。这时就会想用自动裁剪工具进行裁剪,而网上的大多数工具都是定尺寸裁剪需要手动输入裁剪位置,这种还是没法实现自动识别图片间的分界线并裁剪的操作。而此时想起曾学习过一点机器视觉的内容,就尝试用python和opencv实现整个操作过程,来识别图片分界线并自动裁剪保存。
二 项目流程
实现这个过程的大致流程是先扫描给定文件下的所有文件,对扫描出来的文件名进行取后缀处理,将文件后缀与图片类型进行比对,如是图像文件则先将图片转换为灰度图然后去噪,再进行边缘轮廓提取,得到图像边缘轮廓后可以进行图像形态学处理使得分界线更明显,再运用霍夫直线变换进行直线检测,对直线检测的结果进行处理只留下水平直线,将直线的纵坐标提取并以升序排序,排序后进行裁剪保存,如此循环直到将文件夹下的图像文件处理完。而实现以上过程的难点就在于提取出图 片的轮廓。
三 图像边缘提取
由于需要提取图片的边缘轮廓,想到可以用Sobel算子进行处理。图像梯度计算的是图像变化的速度,对于图像的边缘部分,其灰度值变化较大,梯度值也较大;相反,对于图像中比较平滑的部分,其灰度值变化较小,相应的梯度值也较小。一般情况下,图像梯度计算的是图像的边缘信息。Sobel 算子是一种离散的微分算子,该算子结合了高斯平滑和微分求导运算。该算子利用局部差分寻找边缘,计算所得的是一个梯度的近似值。我们想要得到的是水平分界线,可以计算水平垂直方向的偏导数从而得到边缘轮廓。
在opencv中应用sobel算子计算计算图像梯度
import cv2
import numpy as np# 加载图片并转换为灰度图
img = cv2.imread(r"D:\Image\lsfjlejljlkk (2).jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 对灰度图进行高斯模糊
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 使用Sobel算子计算梯度
grad_x = cv2.Sobel(blurred, cv2.CV_16S, 1, 0)
grad_y = cv2.Sobel(blurred, cv2.CV_16S, 0, 1)
# 将梯度转换为绝对值
abs_grad_x = cv2.convertScaleAbs(grad_x)
abs_grad_y = cv2.convertScaleAbs(grad_y)
# 合并梯度
grad = cv2.addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0)
# 对梯度进行二值化处理
thresh,binary=cv2.threshold(grad,80,255,cv2.THRESH_BINARY)
cv2.imwrite(r"D:\Image\lsfjlejljlkk (2).jpg", binary,[cv2.IMWRITE_JPEG_QUALITY,98])
图片处理后的结果
除了应用sobel算子还可以使用Canny 边缘检测
import cv2
import numpy as np# 加载图片并转换为灰度图
img = cv2.imread(r"D:\Image\lsfjlejljlkk (2).jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#cany处理
cany=cv2.Canny(gray, 50, 150, apertureSize=3)
cv2.imwrite(r"D:\Image\lsfjlejljlkk (3).jpg", cany,[cv2.IMWRITE_JPEG_QUALITY,98])
从以上结果可以看出来不管是用sobel还是cany,处理后的图像都能明显找出分界线,但仔细观察就会发现图像中除了有分界线还有其他元素,并且分界线不是很连续有锯齿状,可以考虑使用形态学进行处理,先对图像进行膨胀后在进行腐蚀
import cv2
import numpy as np# 加载图片并转换为灰度图
img = cv2.imread(r"D:\Image\46777cb7e3ae46d6b724b377a6dac721.jpeg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_filtering=cv2.GaussianBlur(gray,(3,3),0,0)
cany = cv2.Canny(gray_filtering, 50, 150, apertureSize=3)
kernel = np.ones((2, 9), np.uint8)
kernel1 = np.ones((1, 40), np.uint8)
cany = cv2.dilate(cany, kernel, iterations=2)
cany = cv2.erode(cany, kernel1, iterations=3) # 腐蚀
kernel = np.ones((5, 1), np.uint8)
morphology1 = cv2.erode(cany, kernel, iterations=5)
morphology2 = cv2.subtract(cany, morphology1)#相减除去多余元素
cv2.imwrite(r"D:\Image\lsfjlejljlkk (5).jpg", morphology2,[cv2.IMWRITE_JPEG_QUALITY,98])
经过膨胀腐蚀处理后分界线更加明显,且直线的连续性更好了。
四 直线检测
霍夫变换是一种在图像中寻找直线、圆形以及其他简单形状的方法。霍夫变换采用类似于
投票的方式来获取当前图像内的形状集合,该变换由 Paul Hough(霍夫)于 1962 年首次提出。
最初的霍夫变换只能用于检测直线,经过发展后,霍夫变换不仅能够识别直线,还能识别其他
简单的图形结构,常见的有圆、椭圆等。
本次用opencv提供的函数cv2.HoughLinesP()进行直线检测
import cv2
import numpy as npQuantity_factor=0.65
Interval_factor=0.25
img = cv2.imread(r"D:\Image\46777cb7e3ae46d6b724b377a6dac721.jpeg")
high=img.shape[0]
wide=img.shape[1]
Quantity =int(Quantity_factor*wide)
Interval =int(Interval_factor*wide)
# 加载图片并转换为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_filtering=cv2.GaussianBlur(gray,(3,3),0,0)
#使用cany处理图像
cany = cv2.Canny(gray_filtering, 50, 150, apertureSize=3)
kernel = np.ones((2, 9), np.uint8)
kernel1 = np.ones((1, 40), np.uint8)
cany = cv2.dilate(cany, kernel, iterations=2)
cany = cv2.erode(cany, kernel1, iterations=3) # 腐蚀
kernel = np.ones((5, 1), np.uint8)
morphology1 = cv2.erode(cany, kernel, iterations=5)
morphology2 = cv2.subtract(cany, morphology1)#相减除去多余元素
lines = cv2.HoughLinesP(morphology2,1, np.pi/2,Quantity,maxLineGap=Interval) #返回值是三维数组
if lines is not None:lines_img = new_img(high, wide)for line in lines:x1, y1, x2, y2 = line[0]cv2.line(lines_img, (x1, y1), (x2, y2), 255, 1)cv2.imwrite(r"D:\Image\lsfjlejljlkk (6).jpg", lines_img, [cv2.IMWRITE_JPEG_QUALITY, 98])
else:print("没有找到图片裁剪线")
以上就是找出的图片分界线
最后进行裁剪操作就能得到单张图像了
import cv2
import numpy as npQuantity_factor=0.65
Interval_factor=0.25
img = cv2.imread(r"D:\Image\46777cb7e3ae46d6b724b377a6dac721.jpeg")
high=img.shape[0]
wide=img.shape[1]
Quantity =int(Quantity_factor*wide)
Interval =int(Interval_factor*wide)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray_filtering=cv2.GaussianBlur(gray,(3,3),0,0)cany = cv2.Canny(gray_filtering, 50, 150, apertureSize=3)
kernel = np.ones((2, 9), np.uint8)
kernel1 = np.ones((1, 40), np.uint8)
cany = cv2.dilate(cany, kernel, iterations=2)
cany = cv2.erode(cany, kernel1, iterations=3) # 腐蚀
kernel = np.ones((5, 1), np.uint8)
morphology1 = cv2.erode(cany, kernel, iterations=5)
morphology2 = cv2.subtract(cany, morphology1)#相减除去多余元素
lines = cv2.HoughLinesP(morphology2,1, np.pi/2,Quantity,maxLineGap=Interval) #返回值是三维数组
if lines is not None:lines_img = new_img(high, wide)for line in lines:x1, y1, x2, y2 = line[0]cv2.line(lines_img, (x1, y1), (x2, y2), 255, 1)cv2.imwrite(r"D:\Image\lsfjlejljlkk (6).jpg", lines_img, [cv2.IMWRITE_JPEG_QUALITY, 98])fenjieY = []for lint in range(len(lines)):if lines[lint][0][1] == lines[lint][0][3] and lines[lint][0][1] > 0 and lines[lint][0][1] < high - 1:fenjieY.append(lines[lint][0][1])fenjieY.sort()for lie in range(len(fenjieY) - 1):if fenjieY[lie + 1] - fenjieY[lie] < 5:xz = int((fenjieY[lie] + fenjieY[lie + 1]) / 2)fenjieY[lie] = xzfenjieY[lie + 1] = xzfenjieY.extend([0, high - 1])fenjieY = list(set(fenjieY))fenjieY.sort()for lie in range(len(fenjieY) - 1):if fenjieY[lie + 1] - fenjieY[lie] > 500:img1 = img[fenjieY[lie]:fenjieY[lie + 1] + 1, 0:wide]dizhi = r"D:\Image" + "\\" + "lsfjlejljlkk_" + str(lie) + ".jpg"cv2.imwrite(dizhi, img1, [cv2.IMWRITE_JPEG_QUALITY, 98])
else:print("没有找到图片裁剪线")
以下就是拆分结果
第一张
第二张
五 项目代码
以下程序可以自动运行,只需要提供原始图像文件路径和拆分后的输出路径,若发现效果不理想可以自行更改参数进行调整。
import os
import cv2
import numpy as np
#读取文件列表并加载相关参数
img_list=[".jpg",".png",".jpeg",".bmp"]
bassIn_path=r"D:\Image\fen1"
bassOut_path=r"D:\Image\fen1\10"
Quantity_factor=0.65
Interval_factor=0.25
path_list = os.listdir(bassIn_path)
#Cany处理
def canny(img):cany = cv2.Canny(img, 50, 150, apertureSize=3)kernel = np.ones((2, 9), np.uint8)kernel1 = np.ones((1, 40), np.uint8)cany = cv2.dilate(cany, kernel, iterations=2)cany = cv2.erode(cany, kernel1, iterations=3) # 形态学处理 腐蚀return cany
#形态学处理
def morphology(img):kernel = np.ones((5, 1), np.uint8)morphology1 = cv2.erode(img, kernel, iterations=5) # 形态学处理 腐蚀morphology2=cv2.subtract(img, morphology1)return morphology2def new_img(high,wide):img = np.zeros((high, wide), np.uint8)# 黑色色背景img.fill(0)return img#循环处理每个文件
for path_name in path_list:if os.path.splitext(path_name)[-1].lower() in img_list:iput_path_bass = path_name.replace(os.path.splitext(path_name)[-1],'')iput_path=bassIn_path+"\\"+path_name# 读入图片img = cv2.imread(iput_path)print(path_name,"图像属性:",img.shape)high=img.shape[0]wide=img.shape[1]Quantity =int(Quantity_factor*wide)Interval =int(Interval_factor*wide)# 转为灰度图gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)gray_filtering=cv2.GaussianBlur(gray,(3,3),0,0)#进行cany处理edges=canny(gray_filtering)dizhi1 = bassOut_path + "\\" + iput_path_bass + "_01" + ".jpg"cv2.imwrite(dizhi1, edges, [cv2.IMWRITE_JPEG_QUALITY, 98])#形态学处理edges=morphology(edges)dizhi1 = bassOut_path + "\\" + iput_path_bass + "_morphology" + ".jpg"cv2.imwrite(dizhi1, edges, [cv2.IMWRITE_JPEG_QUALITY, 98])#统计概率霍夫线变换lines = cv2.HoughLinesP(edges,1, np.pi/2,Quantity,maxLineGap=Interval) #返回值是三维数组#处理直线检测结果if lines is not None:lines_img=new_img(high,wide)for line in lines:x1, y1, x2, y2 = line[0]cv2.line(lines_img, (x1, y1), (x2, y2), 255, 1)dizhi1 = bassOut_path + "\\" + iput_path_bass + "_lines" + ".jpg"cv2.imwrite(dizhi1, lines_img, [cv2.IMWRITE_JPEG_QUALITY, 98])fenjieY=[]for lint in range(len(lines)):if lines[lint][0][1]==lines[lint][0][3] and lines[lint][0][1]>0 and lines[lint][0][1]<high-1:fenjieY.append(lines[lint][0][1])fenjieY.sort()for lie in range(len(fenjieY)-1):if fenjieY[lie+1]-fenjieY[lie]<5:xz=int((fenjieY[lie]+fenjieY[lie+1])/2)fenjieY[lie]=xzfenjieY[lie+1]=xzfenjieY.extend([0,high-1])fenjieY = list(set(fenjieY))fenjieY.sort()print(path_name,"图像文件处理完成共找到%d条分界线:开始裁剪" % int(len(fenjieY)-2))for lie in range(len(fenjieY)-1):if fenjieY[lie+1]-fenjieY[lie] > 500:img1 = img[fenjieY[lie]:fenjieY[lie+1]+1, 0:wide]dizhi=bassOut_path+"\\"+iput_path_bass+str(lie)+".jpg"cv2.imwrite(dizhi, img1,[cv2.IMWRITE_JPEG_QUALITY,98])print(path_name,"图像裁剪完成")else:print(path_name,"图像不需要裁剪或者无法找到分界线")
python opencv:批量识别拼接图片分界线并进行自动裁剪相关推荐
- python opencv 批量将视频转化为图片
单个的视频转换图片参看: python opencv 把视频转为图片 对于多个视频,采用多线程处理方法 video_path为待转换视频的路径,pic_path为输出图像的路径,输出的图像统一保存在p ...
- 基于python opencv人脸识别的签到系统
基于python opencv人脸识别的签到系统 前言 先看下效果 实现的功能 开始准备 页面的构建 功能实现 代码部分 总结 前言 一个基于opencv人脸识别和TensorFlow进行模型训练的人 ...
- Python OpenCV 批量修改文件夹内所有图片的尺寸
Python OpenCV 批量修改文件夹内所有图片的尺寸 简述 插件 遍历所有文件(包括子文件) 缩放图片尺寸并保存图片 遍历并修改图片 简述 遍历文件夹下的所有子文件(包括自文件夹内的)的图片批量 ...
- python opencv人脸识别考勤系统的完整源码
这篇文章主要介绍了python opencv人脸识别考勤系统的完整源码,本文给大家介绍的非常详细,希望对大家的学习或工作具有一定的参考借鉴价值. 代码如下: import wx import wx.g ...
- 【Opencv】Python+openCV实现全景图拼接(左右两张图片拼接成一张全景图)
Python+openCV实现全景图拼接(左右两张图片拼接成一张全景图) 全景图拼接 思路 具体步骤 代码与结果 代码 效果测试1 效果测试2 全景图拼接 思路 这个就是简单对左右两张图进行拼接,希望 ...
- python 找出图片中的差异点,python opencv对目录下图片进行去重的技巧
使用python opencv对目录下图片进行去重的方法 版本: 平台:ubuntu 14 / I5 / 4G内存 python版本:python2.7 opencv版本:2.13.4 依赖: 如果系 ...
- python图片转视频加特效_使用Python opencv实现视频与图片的相互转换
因为最近要经常转换数据集进行实验,因此记录一下. 1.视频转图片 即为将视频解析为一帧一帧的图片: import cv2 vc=cv2.VideoCapture("/home/hqd/Pyc ...
- Python+OpenCV人脸识别签到考勤系统(新手入门)
Python+OpenCV人脸识别签到考勤系统(新手入门) 前言 项目效果图 项目需要的环境 编译器 辅助开发QT-designer 项目配置 代码部分 核心代码 项目目录结构 后记 正式版改进 项目 ...
- Python脚本批量重命名图片
Python脚本批量重命名图片 # -*- coding: utf-8 -*- """ Created on Tue Mar 23 13:34:59 2021@autho ...
最新文章
- codeblocks安装及使用教程(手把手傻瓜式教学)
- php 正则表达式界限符
- 用python画月亮的代码-用python画月亮的代码是什么?
- 如何使用通用Mapper
- Request转发---应用
- extmail mysql数据库 重启_centos 5.8 x86_64下安装mysql+postfix+extmail+extman+courier-authlib+courier-imap...
- QT分页控件,开源,供大家使用
- mysql round 0.1111_听说Mysql你很豪横?-------------分分钟带你玩转SQL高级查询语句(库函数,存储过程)...
- VC限制只能输入常规数字的CEdit控件
- 输入控件控制输入限制
- android 动画之漂移,Android之自定义Drawable实现灵动的红鲤鱼动画(上篇)
- hdu 1569 1565 (二分图带权最大独立集 - 最小割应用)
- 谷歌大脑科学家 Caffe缔造者 贾扬清 微信讲座
- 符晓《TMS320F28335DSP原理、开发及应用》2017版
- golang html转成pdf,使用_go-wkhtmltopdf_将html转pdf
- Microsoft Edge浏览器设置编码方式
- InputDispatcher: Untrusted touch due to occlusion by
- 设计模式-单例模式,观察者模式
- 基于stm32f103的俄罗斯方块游戏
- HDU - 3966 树链刨分
热门文章
- 使用STM32内部ADC资源读取环境光传感器
- cnpm run dev报错These dependencies were not found:* atpl in ./node_modules/consolidate/lib/consolidate
- 杭电 HDU ACM 1754 I Hate It (线段树)
- html加拼音注释,小学必背古诗80首+带拼音(注释彩打版)(31页)-原创力文档
- 论文笔记:EGAT: Edge Aggregated Graph Attention Networks and Transfer Learning Improve Protein-Protein In
- win7系统如何设置一键锁屏?
- 笔记本外接显示器开hdr后黑屏无法操控
- 2023年四月份图形化一级打卡试题
- GDAL VSI文件扩展(virtual_file_systems扩展)
- 峡谷之巅显示服务器更新,严查LOL峡谷之巅演员、代打 将开启账号人脸识别登录模式...