openCV提取图像中的矩形区域
作者:c19961227 发布时间:2022-06-11 06:38:55
标签:openCV,提取图像
改编自详解利用OpenCV提取图像中的矩形区域(PPT屏幕等) 原文是c++版,我改成了python版,供大家参考学习。
主要思想:边缘检测—》轮廓检测—》找出最大的面积的轮廓—》找出顶点—》投影变换
import numpy as np
import cv2
# 这个成功的扣下了ppt白板
srcPic = cv2.imread('2345.jpg')
length=srcPic.shape[0]
depth=srcPic.shape[1]
polyPic = srcPic
shrinkedPic = srcPic
greyPic = cv2.cvtColor(shrinkedPic, cv2.COLOR_BGR2GRAY)
ret, binPic = cv2.threshold(greyPic, 130, 255, cv2.THRESH_BINARY)
print(binPic.shape)
median = cv2.medianBlur(binPic, 5)
# 进行边缘检测
cannyPic = cv2.Canny(median, 10, 200)
cv2.namedWindow("binary", 0)
cv2.namedWindow("binary2", 0)
cv2.imshow("binary", cannyPic)
# 找出轮廓
contours, hierarchy = cv2.findContours(cannyPic, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
cv2.imwrite('binary2.png', cannyPic)
cv2.imshow("binary2", cannyPic)
i = 0
maxArea = 0
# 挨个检查看那个轮廓面积最大
for i in range(len(contours)):
if cv2.contourArea(contours[i]) > cv2.contourArea(contours[maxArea]):
maxArea = i
#检查轮廓得到分布在四个角上的点
hull = cv2.convexHull(contours[maxArea])
s = [[1,2]]
z = [[2,3]]
for i in hull:
s.append([i[0][0],i[0][1]])
z.append([i[0][0],i[0][1]])
del s[0]
del z[0]
#现在的目标是从一堆点中挑出分布在四个角落的点,决定把图片分为四等份,每个区域的角度来划分点,
#默认四个角分别分布在图像的四等分的区间上,也就是矩形在图像中央
# 我们把所有点的坐标,都减去图片中央的那个点(当成原点),然后按照x y坐标值的正负 判断属于哪一个区间
center=[length/2,depth/2]
# 可以得到小数
for i in range(len(s)):
s[i][0] = s[i][0] - center[0]
s[i][1] = s[i][1] - center[1]
one = []
two = []
three = []
four = []
# 判断是那个区间的
for i in range(len(z)):
if s[i][0] <= 0 and s[i][1] <0 :
one.append(i)
elif s[i][0] > 0 and s[i][1] <0 :
two.append(i)
elif s[i][0] >= 0 and s[i][1] > 0:
four.append(i)
else:three.append(i)
p=[]
distance=0
temp = 0
# 下面开始判断每个区间的极值,要选择距离中心点最远的点,就是角点
for i in one :
x=z[i][0]-center[0]
y=z[i][1]-center[1]
d=x*x+y*y
if d > distance :
temp = i
distance = d
p.append([z[temp][0],z[temp][1]])
distance=0
temp=0
for i in two :
x=z[i][0]-center[0]
y=z[i][1]-center[1]
d=x*x+y*y
if d > distance :
temp = i
distance = d
p.append([z[temp][0],z[temp][1]])
distance=0
temp=0
for i in three :
x=z[i][0]-center[0]
y=z[i][1]-center[1]
d=x*x+y*y
if d > distance :
temp = i
distance = d
p.append([z[temp][0],z[temp][1]])
distance=0
temp=0
for i in four :
x=z[i][0]-center[0]
y=z[i][1]-center[1]
d=x*x+y*y
if d > distance :
temp = i
distance = d
p.append([z[temp][0],z[temp][1]])
for i in p:
cv2.circle(polyPic, (i[0],i[1]),2,(0,255,0),2)
# 给四个点排一下顺序
a=[]
b=[]
st=[]
for i in p:
a.append(i[0])
b.append(i[1])
index=np.lexsort((b, a))
for i in index:
st.append(p[i])
p = st
print(p)
pts1 = np.float32([[p[0][0],p[0][1]],[p[1][0],p[1][1]],[p[2][0],p[2][1]],[p[3][0],p[3][1]]])
# dst=np.float32([[0,0],[0,srcPic.shape[1]],[srcPic.shape[0],0],[srcPic.shape[0],srcPic.shape[1]]])
dst=np.float32([[0,0],[0,600],[400,0],[400,600]])
# 投影变换
M = cv2.getPerspectiveTransform(pts1,dst)
cv2.namedWindow("srcPic2", 0)
cv2.imshow("srcPic2", srcPic)
#dstImage = cv2.warpPerspective(srcPic,M,(srcPic.shape[0],srcPic.shape[1]))
dstImage = cv2.warpPerspective(srcPic,M,(400,600))
# 在原图上画出红色的检测痕迹,先生成一个黑色图
black = np.zeros((shrinkedPic.shape[0], shrinkedPic.shape[1]), dtype=np.uint8)
# 二值图转为三通道图
black3 = cv2.merge([black, black, black])
# black=black2
cv2.drawContours(black, contours, maxArea, 255, 11)
cv2.drawContours(black3, contours, maxArea, (255, 0, 0), 11)
cv2.imwrite('cv.png', black)
cv2.namedWindow("cannyPic", 0)
cv2.imshow("cannyPic", black)
cv2.namedWindow("shrinkedPic", 0)
cv2.imshow("shrinkedPic", polyPic)
cv2.namedWindow("dstImage", 0)
cv2.imshow("dstImage", dstImage)
# 等待一个按下键盘事件
cv2.waitKey(0)
# 销毁所有创建出的窗口
运行效果
用到的图片
来源:https://blog.csdn.net/c19961227/article/details/90693098


猜你喜欢
- 前言在Django使用Celery异步发送邮件的过程中,遇到Celery日志提示任务已接收,但实际上任务并没有执行,解决后特此记录。使用版本
- Python进程池是Python标准库中multiprocessing模块提供的一种用于管理进程的方式。它可以使Python程序以并行的方式
- 首先,想要实现的功能是递归遍历文件夹,遇到满足条件的文件时,用yield返回该文件的位置。如果不用递归器,可以这样实现:path_list
- 这是《python基础教程》后面的实践,照着写写,一方面是来熟悉python的代码方式,另一方面是练习使用python中的基本的以及非基本的
- 问题你想根据一组语法规则解析文本并执行命令,或者构造一个代表输入的抽象语法树。 如果语法非常简单,你可以不去使用一些框架,而是自己写这个解析
- 实现思路是先获取到当前最上面活动的窗口信息,然后提取该窗口的名称信息。之后获取窗口的坐标信息,即左上角的开始坐标及右下角的结束坐标。最后直接
- 前段时间在生活中偶尔需要对某些文件进行重命名,而且是随机名字,刚开始是手动重命名然后在键盘上胡乱打一些字母数字,时间长了发现也挺麻烦的,于是
- 这是asp利用dictionary创建二维数组的例子,这样做的优点是:1、数组下标可以是字符串2、长度不是固定的<'% ’==
- 本文通过实例介绍了MySQL中的group_concat函数的使用方法,比如select group_concat(name) 。 MySQ
- 本文研究的主要是python删除过期log文件的相关内容,具体介绍如下。1. 用Python遍历目录os.walk方法可以很方便的得到目录下
- 目录模板基本语法编写主页模板准备虚拟数据渲染主页模板总结在一般的 Web 程序里,访问一个地址通常会返回一个包含各类信息的 HTML 页面。
- 本文实例为大家分享了python机器学习实现决策树的具体代码,供大家参考,具体内容如下# -*- coding: utf-8 -*-&quo
- 按照本地时间的javascript date.getDate()方法返回月份的一天,在指定日期。由getDate返回的值是1到3
- 一、基本使用最近研究了一下 el-upload组件 踩了一些小坑 写起来大家学习一下很经常的一件事情 经常会去直接拷贝 elem
- 1.下载mysql网址: https://dev.mysql.com/downloads/mysql/2.选择源码包,通用版点击下载直接下载
- 从我们论坛中收集了这段HTML制作页面需要最大化、最小化时可以借鉴参考。最大化效果:<OBJECT id="max
- 你是否想知道为什么事务日志文件会变得越来越大?事务日志有时候甚至会比你的实际数据库文件还要大,尤其是在应用数据仓库的情况下。为什么会发生这种
- 1) ERROR 1222 (21000): The used SELECT statements have a different num
- 现有1.php内容如下: <?phpecho 'hi\nhi';在命令行中执行该文件: bash >> p
- 关于string的split 和 join 方法对导入os模块进行os.path.splie()/os.path.join() 貌似是处理机