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

目录

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相关内容,欢迎关注公众号“音视频开发之旅”,一起学习成长。

欢迎交流

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

校招说明书

3400字的详细说明,介绍了程序员类岗位校招的整体时间节点和招聘流程。还对一些常见的问题进行讨论,例如内推、offer和三方、实习等。 第一章介绍基本的术语,第二章介绍整个校招的重要流程及时间点,然后第三章介绍每次招聘要经过的…

网络:HTTP协议

目录 序列化与反序列化 守护进程 网络计算器的实现 HTTP协议 http的代码演示 HTTPS 初步理解三次握手,四次挥手 ①tcp是面向连接的通信协议,在通信之前,需要进行3次握手,来进行连接的建立(谁connect谁握手) ②当tcp在断开…

《软件方法》剖析“提灯定损”,金将军和南丁格尔

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 这几天,江西出了“提灯定损”事件,成为“周公子”、“指鼠为鸭”之后的又一个大IP。 我也蹭一下这个IP,谈一谈软件开发中的业务建模和需求。 图1 “…

git上传到本地仓库

摘要:本地初始化init仓库,进行pull和push;好处是便于利用存储设备进行git备份 git init --bare test.git 随便到一个空的目录下git clone 然后使用git上传 把git仓库删除之后再clone一次验证一下是否上传成功: 如果在ubantu上面没…

实用技巧:如何取消app的截屏禁用

因为我想要在小鹅通App做笔记,但是被小鹅通App禁用截屏了,这真是一个很糟糕的使用体验,虽然可能是为了保护商家权益…… 方法1 可以让商家设置课程可以截屏 方法2 手机root,安装Xposed框架,利用Xposed框架上面的插件我们可以对手机进行高度定制化,而安装Xposed框架的…

Emacs之实现复制当前已打开文件buffer(一百三十五)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

【嵌入式智能产品开发实战】(十六)—— 政安晨:通过ARM-Linux掌握基本技能【Linux shell揭秘】

目录 简述 开始 深入探究Linux内核 1.系统内存管理 2.软件程序管理 3.硬件设备管理 4.文件系统管理 GNU实用工具 1.核心GNU实用工具 2.shell Linux桌面环境 1.X Window软件 2.KDE Plasma桌面 3.GNOME桌面 4.其他桌面 Linux发行版 核心Linux发行版 特定用途的…

卷积篇 | YOLOv8改进之引入全维度动态卷积ODConv | 即插即用

前言:Hello大家好,我是小哥谈。ODConv是一种关注了空域、输入通道、输出通道等维度上的动态性的卷积方法,一定程度上讲,ODConv可以视作CondConv的延续,将CondConv中一个维度上的动态特性进行了扩展,同时了考虑了空域、输入通道、输出通道等维度上的动态性,故称之为全维度…

在一套Dockerfile中完成编译和运行环境部署

大纲 解释型语言编译环境解释环境编译型语言编译环境运行环境 方法编译环境安装系统安装编译依赖下载代码特殊处理(可以忽略)编译准备(可以忽略)编译打包依赖(编译结果) 运行环境安装操作系统安装运行时依赖…

RabbitMQ高级-应用问题、集群搭建

1.消息补偿 消息可靠性保障:——消息补偿机制 需求:100%确保消息发送成功 2.幂等性保障 幂等性指一次和多次请求某一资源,对于资源本身应该具有同样的结果。也就是说,其任意多次执行对资源本身所产生的影响均与第一次执行的影响…

AI编程005/ 逆向生成mysql的建表语句

1/ 通过insert into 语句生成建表语句 有些时候我们能获取到表的insert语句,但是没有表结构。我们可以借助AI工具,让其逆向生成mysql的建表语句。 提示词如下: 根据下面的SQL语句,逆向生存mysql的建表语句,每个字段…

Redis配置与优化

目录 引言 一、关系型数据库与非关系型数据库 1、关系型数据库 2、非关系型数据库 3、关系型数据库和非关系型数据库的区别 1.数据存储方式不同 2.扩展方式不同 3.对事物性的支持不同 4、非关系型数据库产生背景 二、Redis简介 1、Redis优点 2、Redis为什么这麽快&…

企业员工岗前培训管理系统的设计与实现(论文+源码)_kaic

摘 要 有效的处理想要的相关信息和如何传播有效的信息,一直是人类不断探索的动力。人类文明火种的传承都是通过了多种媒介作为载体,也是随着社会生产力的发展不断的更新。随着互联网的到来,信息传播与管理都上升了一个新的台阶,并…

基于单片机的全自动洗衣机系统仿真设计

**单片机设计介绍,基于单片机的全自动洗衣机系统仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的全自动洗衣机系统仿真设计概要是关于利用单片机技术实现全自动洗衣机控制功能的系统设计概述。以…

【5】JavaScript - 控制语句 循环[ for/while ]

控制语句 while/do...while 语句while 语句:do...while 语句:两者的区别无限循环 for 语句普通的 for 循环for...in 循环for...of 循环 循环过程:跳出/跳过跳出跳过 循环嵌套扩展延申:做一次杠精 当前 控制语句 章节主要介绍 循环…

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

点击查看专栏目录 文章目录 一、pdal_kazhdan介绍二、pdal下载三、文件分析四、pro文件五、编译实践一、pdal_kazhdan介绍 pdal_kazhdan 是 PDAL(Point Data Abstraction Library)相关的 Kazhdan 算法的实现。PDAL 是一个用于处理和分析点云数据的开源库,而 Kazhdan 算法通常…

【教学类-09-09】20240406细线迷宫图05(正方形)30格+动物+箭头(15CM横版一页-1份横版)

作品展示: 背景需求: 增加迷宫图的吸引力,起点的地方放一个小动物。 素材准备: 图片来自midjounery文生图(四图),但同种动物只留1个(如4个老鼠只保留一只老鼠)&#xff…

YOLOv8 UI界面设计+热力图显示

进入可视化设计界面,设计UI pyside6-designer 设计好UI保存,然后通过以下命令将ui文件保存为py pyside6-uic myui.ui > myui.py 通过以下命令将资源文件qrc保存为py pyside6-rcc my_rc.qrc > my_rc.py 写主窗口函数实现功能... 项目基于yol…

React - 连连看小游戏

简介 小时候经常玩连连看小游戏。在游戏中,当找到2个相同的元素就可以消除元素。 本文会借助react实现连连看小游戏。 实现效果 实现难点 1.item 生成 1. 每一个图片都是一个item,items数组的大小为size*size。 item对象包括grid布局的位置,…

哈佛大学商业评论 -- 第二篇:增强现实是如何工作的?

AR将全面融入公司发展战略! AR将成为人类和机器之间的新接口! AR将成为人类的关键技术之一! 请将此文转发给您的老板! --- 本文作者:Michael E.Porter和James E.Heppelmann 虽然物理世界是三维的,但大…