音视频开发之旅(81)- 图片视频“黑边”检测与去除

news2025/1/15 16:36:43

目录

1.“黑边“的场景

2. 二值化--单一颜色边缘的图像

3. canny边缘检测+霍夫直线变换--处理负责的边缘图像

4. 性能优化

5. 资料

在页面展示中,如果图片/视频有黑边,比较影响体验,我我们今天实现下对图片/视频进行黑边检测。检测到黑边的信息之后,使用ffmpeg或者opencv进行裁剪即可实现黑边的去除即可。

一、“黑边“的场景

黑边的场景有很多种类型:单一颜色的黑边;边界不明显的黑边;三明治黑边;黑边与内容有交叉的场景等等,如下图所示

图片

设计一个通用的黑边检测与去除兼容上面各种场景是一个有意思的事情。下面给出两种实现方案:二值化;Canny边缘检测+霍夫之间检测

二、二值化--单一颜色边缘的图像

对于常规的图片,使用canny边缘检测,即可区分除边界

图片

主要思路:

通过对图片进行GaussianBlur高斯模糊减少噪声;然后进行threshold二值化处理,获取黑白值;通过findContours查找轮廓;选择除轮廓中最大的近似矩形的轮廓;然后获取其边界并进行裁剪

代码和详细说明如下:

def docropBlackEdges(imagepath,outputImagePath):    #读取图片,并把图片转为灰度图    img = cv2.imread(imagepath)    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)        # 消除噪声,使用高斯模糊减少图像中的噪声,使轮廓更加准确    gray = cv2.GaussianBlur(gray, (3,3), 0) 
    #二值化处理,像素值大于1的设置为255(白色),其余的设置为0(黑色)    _, thresh = cv2.threshold(gray, 1, 255, cv2.THRESH_BINARY + cv2.THRESH_BINARY)
    #查找轮廓,这里使用RETR_EXTERNAL(只检测外轮廓)    #CHAIN_APPROX_SIMPLE 表示压缩垂直 水平和对角线元素,指标来他们的终点信息,减少轮廓点的数量    contours,hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)        #选择最大的轮廓    biggest = np.array([])    max_area = 0    for cntrs in contours:        #计算轮廓的面积        area = cv2.contourArea(cntrs)        #计算轮廓的周长        peri = cv2.arcLength(cntrs, True)                #对轮廓点进行近似,找到近似为矩形的轮廓        approx = cv2.approxPolyDP(cntrs, 0.02 * peri, True)        if area > max_area and len(approx) == 4:            biggest = approx            max_area = area    cnt = biggest        #通过找到的最大轮廓,计算器边界矩形,然后进行裁剪    if len(cnt)>0:        x, y, w, h = cv2.boundingRect(cnt)         crop = img[y:y+h, x:x+w]        cv2.imwrite(outputImagePath,crop)

这种方法,对于单一颜色边界,处理比较好,处理速度也比较快,但是对于,相对复杂的边界,就无法正常的检测,如下图

图片

三、canny边缘检测+霍夫直线变换--处理负责的边缘图像

图片

主要思路:

读取图片转为灰度图;使用GaussianBlur进行去噪;然后进行Canny边缘检测;再使用霍夫直线检测进行直线检测获取边界;最后进行裁剪​​​​​​​

def docropBlackEdges(imagepath,outputImagePath):    image = cv2.imread(imagepath)    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)    blurred = cv2.GaussianBlur(gray, (3, 3), 0)    edge = cv2.Canny(blurred, 1, 150)
    lines = lines_detector_hough(edge)    leftX,rightX,topY,bottomY =calculateCropRange(image, lines,outputImagePath)其中lines_detector_hough的实现https://github.com/o0o0o0o0o0o0o/image-processing-from-scratch/blob/master/hough%20transform/HoughTransform.pydef lines_detector_hough(edge,ThetaDim = None,DistStep = None,threshold = None,halfThetaWindowSize = 2,halfDistWindowSize = None):    '''    :param edge: 经过边缘检测得到的二值图    :param ThetaDim: hough空间中theta轴的刻度数量(将[0,pi)均分为多少份),反应theta轴的粒度,越大粒度越细    :param DistStep: hough空间中dist轴的划分粒度,即dist轴的最小单位长度    :param threshold: 投票表决认定存在直线的起始阈值    :return: 返回检测出的所有直线的参数(theta,dist)    @author: bilibili-会飞的吴克    '''    imgsize = edge.shape    if ThetaDim == None:        ThetaDim = 90    if DistStep == None:        DistStep = 1    MaxDist = np.sqrt(imgsize[0]**2 + imgsize[1]**2)    DistDim = int(np.ceil(MaxDist/DistStep))
    if halfDistWindowSize == None:        halfDistWindowSize = int(DistDim/50)    accumulator = np.zeros((ThetaDim,DistDim)) # theta的范围是[0,pi). 在这里将[0,pi)进行了线性映射.类似的,也对Dist轴进行了线性映射
    sinTheta = [np.sin(t*np.pi/ThetaDim) for t in range(ThetaDim)]    cosTheta = [np.cos(t*np.pi/ThetaDim) for t in range(ThetaDim)]
    for i in range(imgsize[0]):        for j in range(imgsize[1]):            if not edge[i,j] == 0:                for k in range(ThetaDim):                    accumulator[k][int(round((i*cosTheta[k]+j*sinTheta[k])*DistDim/MaxDist))] += 1
    M = accumulator.max()
    if threshold == None:        threshold = int(M*2.3875/10)    result = np.array(np.where(accumulator > threshold)) # 阈值化    temp = [[],[]]    for i in range(result.shape[1]):        eight_neiborhood = accumulator[max(0, result[0,i] - halfThetaWindowSize + 1):min(result[0,i] + halfThetaWindowSize, accumulator.shape[0]), max(0, result[1,i] - halfDistWindowSize + 1):min(result[1,i] + halfDistWindowSize, accumulator.shape[1])]        if (accumulator[result[0,i],result[1,i]] >= eight_neiborhood).all():            temp[0].append(result[0,i])            temp[1].append(result[1,i])
    result = np.array(temp)    # 非极大值抑制
    result = result.astype(np.float64)    result[0] = result[0]*np.pi/ThetaDim    result[1] = result[1]*MaxDist/DistDim
    return result

这个实现时相当耗时的,主要在accumulator 3层for循环那里

四、性能优化

cv中实现了HoughLines,可用通过下面的方式快速的掉用,相比上面的python版本,耗时降低1-2个数量级​​​​​​

def docropBlackEdges(imagepath,outputImagePath):    image = cv2.imread(imagepath)    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)    blurred = cv2.GaussianBlur(gray, (3, 3), 0)    edge = cv2.Canny(blurred, 1, 150)    #使用cv内部实现的HoughLines(c++版本)大大减少处理是耗时    tlines = cv2.HoughLines(edge,1.0,np.pi/180,150)

五、资料

1.图解cv2.HoughLines

https://blog.csdn.net/qq_54185421/article/details/126661672

2. 检测图像边缘黑边裁剪算法 python 图像的边缘检测

https://blog.51cto.com/u_16213663/7834273

3.Hough变换-理解篇

https://blog.csdn.net/abcjennifer/article/details/7448513


 

感谢你的阅读

接下来我们继续学习输出AIGC相关内容,欢迎关注公众号“音视频开发之旅”,一起学习成长。

欢迎交流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1569734.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL Server维护计划

目录 1.概述 2.启动SQL Server 代理服务 3.制定维护计划 4.验证维护计划 5.删除维护计划 1.概述 此文还是存货哈! SQL Server 2008 R2维护计划。 2.启动SQL Server 代理服务 在设置维护计划之前,必须先确保SQL Server 代理服务已启动。启动方法如…

Html提高——视频标签音频标签及其相关属性

HTML5 在不使用插件的情况下&#xff0c;也可以原生的支持音视频格式文件的播放&#xff0c;当然&#xff0c;支持的格式是有限的。 1、video标签 1.1、video标签的语法 <video src"文件地址" controls"controls"></video> video标签的内部…

SAP FI学习笔记04 - 基础知识 - 新规会计科目,用 应收账款科目 做个例子

上一章讲了 应付账款 的来源及操作。 SAP FI学习笔记03 - 应付账款-CSDN博客 本章先尝试做一个会计科目&#xff0c;然后再用 应收账款 科目做个例子。 应收账款 和 应付账款 一样&#xff0c;也有两个视图。 1&#xff0c;新建几个会计科目 这一章来尝试着创建会计科目。 …

Qt QML的枚举浅用

QML的枚举用法 序言概念命名规则在QML定义枚举的规范 用法QML的枚举定义方法供QML调用的&#xff0c;C的枚举定义方法 序言 概念 QML的枚举和C的其实差不多&#xff0c;但是呢&#xff0c;局限比较多&#xff0c;首先不能在main.qml里定义&#xff0c;也不能在子项中定义。 …

Java spring 01 (图灵)

01.依赖注入 这里两个方法用到了datasource方法&#xff0c;不是bean这样的使用&#xff0c;没有autowird 会创建两个datasource configuration 会运行代理模式 会产生一个AppConfig的代理对象 这个代理对象会在spring的容器先找bean&#xff0c;datasource此时已经创建了be…

ubuntu无法粘贴复制windows中的内容,分辨率无法自适应电脑自带系统

1、直接在命令行执行以下命令 sudo apt-get autoremove open-vm-tools //卸载已有的工具 sudo apt-get install open-vm-tools //安装工具open-vm-tools sudo apt-get install open-vm-tools-desktop //安装open-vm-tools-desktop 2、重启Ubuntu系统即可 3.如果上述…

【QT+QGIS跨平台编译】056:【pdal_lazperf+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、pdal_lazperf介绍二、pdal下载三、文件分析四、pro文件五、编译实践一、pdal_lazperf介绍 pdal_lazperf 是 PDAL(Point Data Abstraction Library)的一个插件,用于处理点云数据。PDAL 是一个开源的库,用于处理和分析地理空间数据,特别是点云…

Linux集群部署项目

目录 一&#xff0c;环境准备 1.1.安装MySQL 1.2.安装JDK 1.3.安装TomCat 1.4.安装Nginx 二&#xff0c;部署 2.1.后台服务部署 2.2.Nginx配置负载均衡及静态资源部署 一&#xff0c;环境准备 1.1.安装MySQL 将MySQL的安装包上传至服务器 查看系统中是否存在mariadb&…

了解 Solidity 语言:构建智能合约的首选编程语言

了解 Solidity 语言&#xff1a;构建智能合约的首选编程语言 Solidity 是一种用于编写智能合约的高级编程语言&#xff0c;广泛应用于以太坊和其他以太坊虚拟机&#xff08;EVM&#xff09;兼容的区块链平台。它是以太坊智能合约的首选语言之一&#xff0c;具有丰富的功能和灵活…

GD32F470_GY-SHT31-D 数字温湿度传感器模块移植

2.11 SHT30温湿度传感器 2.11.1 模块来源 采购链接&#xff1a; GY-SHT31-D 数字温湿度传感器模块 资料下载链接&#xff1a; https://pan.baidu.com/s/1kisMJspcV6Qdr1ye9ElOlQ 2.11.2 规格参数 工作电压&#xff1a;2.4-5.5V 工作电流&#xff1a;0.2~1500uA 温度测量范围&a…

微软文本转语音和语音转文本功能更新,效果显著!

今天我要和大家分享一个新功能更新——微软的文本转语音和语音转文本功能。最近&#xff0c;微软对其AI语音识别和语音合成技术进行了重大升级&#xff0c;效果非常好&#xff0c;现在我将分别为大家介绍这两个功能。 先来听下这个效果吧 微软文本转语音和语音转文本功能更新 …

CVPR24_ArGue: Attribute-Guided Prompt Tuning for Vision-Language Models

Abstract 尽管软提示微调在调整视觉语言模型以适应下游任务方面表现出色&#xff0c;但在处理分布偏移方面存在局限性&#xff0c;通过属性引导提示微调&#xff08;Attribute-Guided&#xff0c;ArGue&#xff09;来解决这个问题 Contributions 与直接在类名之前添加软提示…

浅析JavaWeb内存马基础原理与查杀思路

文章目录 前言Java内存马内存马分类&原理JavaWeb三大组件注入Servlet内存马注入Filter型内存马JAVA Agent内存马 哥斯拉木马0x01 WebShell0x02 MemShell0x03 FilterShell0x04 Arthas排查0x05 scanner查杀 总结 前言 几年前写过《Web安全-一句话木马》&#xff0c;主要介绍…

大意了MySQL关键字EXPLAIN

一、问题 然后explain带了单引号、以区别其关键字 二、报错如下 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near explain, us.nickname AS user_send_nickname, ua.nickname…

探索未来智慧酒店网项目接口架构

在数字化时代&#xff0c;智慧酒店已成为酒店业发展的重要趋势之一。智慧酒店网项目接口架构作为支撑智慧酒店运营的核心技术之一&#xff0c;其设计和优化对于提升用户体验、提高管理效率具有重要意义。本文将深入探讨智慧酒店网项目接口架构的设计理念和关键要素。 ### 智慧…

上位机图像处理和嵌入式模块部署(qmacvisual并发执行)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 类似于qmacvisual这样的软件&#xff0c;其实价格并不便宜。比如大家熟知的halcon、vision pro、vision master这样的软件&#xff0c;最便宜的版本…

练习实践-TLS02-会话恢复的两种形式-Session ID/SessionTicket

参考来源&#xff1a; 书籍&#xff1a;深入浅出https-从原理到实战&#xff08;作者&#xff1a;虞卫东&#xff09; 抓包分析文件可下载&#xff0c;来自github上的作者上传资源 会话恢复机制的背景 当客户端和服务器端握手成功&#xff0c;建立了一个完整的 TLS 连接&…

基于keepalived+gtid+双vip半同步主从复制的MySQL高性能集群

项目名称&#xff1a;基于keepalivedgtid双vip半同步主从复制的MySQL高性能集群 目录 项目名称&#xff1a;基于keepalivedgtid双vip半同步主从复制的MySQL高性能集群 项目规划图 1.配置4台MySQL服务器&#xff08;1台master&#xff0c;2台slave&#xff0c;1台backup&a…

【Django开发】0到1美多商城项目md教程第5篇:短信验证码,1. 避免频繁发送短信验证码逻辑分析【附代码文档】

美多商城完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;欢迎来到美多商城&#xff01;&#xff0c;项目准备。展示用户注册页面&#xff0c;创建用户模块子应用。用户注册业务实现&#xff0c;用户注册前端逻辑。图形验证码&#xff0c;图形验证码接口设…

江协STM32:定时器定时中断和定时器定时闹钟

定时器中断 新建文件 按这个图来编写程序 第一步&#xff1a;RCC开启时钟&#xff0c;定时器到基准时钟和整个外设到工作时钟就会同时打开 第二步&#xff1a;选择时基单元的时钟源&#xff0c;对于定时中断选择内部时钟源 第三步&#xff1a;配置时基单元&#xff0c;ARR,P…