基于Visual studio+Opencv+Python的透视变换、图像处理(灰度化、二值化、Canny边缘检测)模型——以2015数学建模A题太阳影子定位为例

最近话少,较认真,闲言少叙。
2015A数学建模赛题(不完整)

如何确定视频的拍摄地点和拍摄日期是视频数据分析的重要方面,太阳影子定位技术就是通过分析视频中物体的太阳影子变化,确定视频拍摄的地点和日期的一种方法。
4.附件4为一根直杆在太阳下的影子变化的视频,并且已通过某种方式估计出直杆的高度为2米。请建立确定视频拍摄地点的数学模型,并应用你们的模型给出若干个可能的拍摄地点。
如果拍摄日期未知,你能否根据视频确定出拍摄地点与日期?

问题分析

原文附件中所给的视频格式是.avi格式,通过问题四我们可以了解到,本题解决问题关键在于如何从视频中提取关键要素(本题,不用前三题的结论与模型这题是做不出的。有了前三题的模型解本题相当简单,只需要将影长数据带入模型即可。当然这是在已经从视频提取影长信息后,才有的操作,简而言之,本题关键在于如何从视频提取需要的影长数据,这也是本文主要介绍的内容)。
视频提取关键帧,即截图,是最常见的手段之一,因为原始视频共有40min40s左右,所以可以以2min为分割点,提取截图,共有21张图片,随机可以用photoshop量尺工具量取影长,与杆长比例求解,即可得影长数据。
?????如果真的这样做的话,本文也就不存在,截图谁不会~~,我相信这也不是本题得初衷,先举一个例子:


这里有两张图片,已知笔长15cm,那从两张照片估算荧光笔得长度,哪一张图片估算的准确,第二张图片准确无疑,但是原理是什么,为什么第一张图存在这么大的误差?——透视畸变。
图像畸变对图片本身的影响
1.视频本身存在的透视畸变使影子投影到二维图像时出现距上的缩短
2.视频本身存在的拍摄角度倾斜问题会使截取一帧图像时产生梯形畸变

所涉及名词の解释

透视畸变&梯形畸变

透视畸变:
指图像使用二维方法表现三维的关系时,由于小孔成像原理,两平行线必在极远点相交,两平行线是用不可能相交的,图像会出现近大远小的现象,即发生畸变,如图4-4-1-1所示,不能准确刻画物体的准确特征。注意透视畸变是一种成像变形的现象,与我们平时所说的畸变产生原理不同,并不是我们平日里所说的畸变。
透视畸变在二维图像的表现(如下图)

梯形畸变:
以摄像机一类数字设备拍摄目标物时,由于拍摄距离、角度等因素的限制,摄像头往往不方便垂直于地面(或被拍摄平面)获取图像,这样就产生了较大的畸变,使得图像质量下降给后续的图像处理带来影响,这种情况下,畸变主要包括径向畸变和倾斜畸变两种。
在倾斜畸变中,梯形畸变便是最常见的畸变之一。
透视变换(Perspective Transformation)
是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面(透视面)绕迹线(透视轴)旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换,常用于图像的校正。
Opencv(Open Source Computer Vision Library)
是一个基于BSD许可(开源)发行的跨平台计算机视觉软件库,提供Python、MATLAB等语言接口,实现了图像处理与计算机视觉等高级通用算法。
Python
是一种计算机程序设计语言。是一种面向对象的动态类型语言,可以应用于图像处理、机器视觉等领域,是一种易读、易维护,并且被大量用户所欢迎的、用途广泛的编程语言。

基于Visual studio+Opencv+Python的逆透视图形变化处理(数学公式本文不再给出,怕过于冗长)

借助计算机辅助,在Visual studio平台上搭建Python开发环境,运行Opencv内置函数命令,对图像进行处理,即可得到矩阵A即透视变换矩阵,通过透视变换矩阵,借助编程,即可得到进行图像矫正后的图像,通过这种方法可以有效减少由于透视畸变与梯形畸变带来的图形处理误差。

视频处理

本文采用Opencv内置的函数cv2.VideoCapture(‘Appendix4.avi’)截取视频特定帧的画面(程序见附录四),并保存到指定文件夹下以备图像的处理操作。
因为附件一、二所给数据是21组,所以这里我们以2分钟作为一个分割点,一共导出21张光影图片。
视频处理代码:

import cv2
vc = cv2.VideoCapture('Appendix4.avi')  # 读入视频文件
f = 1
i = 1
if vc.isOpened():  # 判断是否正常打开rval, frame = vc.read()
else:rval = False
timeF = 25  # 视频帧计数间隔频率
while rval:  # 循环读取视频帧rval, frame = vc.read()if f % timeF == 0:  # 每隔timeF帧进行存储操作cv2.imwrite('D:\PYTHON\opencv_py\py_open\py_open\ ' + str(i) + '.jpg', frame)  # 存储为图像i = i + 1print("i:"+str(i)+',frame:'+str(f))f = f + 1cv2.waitKey(1)
vc.release()

图像预处理

透视变换图形处理

透视变换图形处理最重要的步骤是求出透视变化矩阵,具体计算公式在上文已经叙述,借助计算机编程算法得出透视变化矩阵:

借助Visual studio+Opencv编程(源程序见附录五)将截取的21张光影图片进行透视化处理并进行局部放大,结果如下图所示:

由图4-4-3-1可知,透视变换对处理由于图片摄像角度不正确、存在透视畸变等缺陷而造成的一系列图像问题,有很好的效果。
透视变换代码

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('hyq.jpg')
rows, cols = img.shape[:2]
# 原图中书本的四个角点
pts1 = np.float32([[700, 100], [2000, 100], [700, 1000], [2000, 1000]])
# 变换后分别在左上、右上、左下、右下四个点
pts2 = np.float32([[0, 0], [2000, 0], [0, 1000], [2000, 1000]])
# 生成透视变换矩阵
M = cv2.getPerspectiveTransform(pts1, pts2)
# 进行透视变换
dst = cv2.warpPerspective(img, M, (1800, 1000))
plt.subplot(121), plt.imshow(img[:, :, ::-1]), plt.title('input')
plt.subplot(122), plt.imshow(dst[:, :, ::-1]), plt.title('output')
# img[:, :, ::-1]是将BGR转化为RGB
#cv2.imwrite('20_20.jpg', dst)
cv2.namedWindow('hyq1',0)
cv2.imshow("hyq1", dst)
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()

灰度化处理

将彩色图像转化成为灰度图像的过程成为图像的灰度化处理,其仍然反映了整幅图像的整体和局部的色度和亮度等级的分布和特征。
根据RGB和YUV颜色空间的变化关系可建立亮度Y与R、G、B三个颜色分量的对应关系:


灰色处理代码

import cv2
import numpy as npif __name__ == "__main__":img_path = "11_11.jpg"img = cv2.imread(img_path)#获取图片的宽和高width,height = img.shape[:2][::-1]#将图片缩小便于显示观看img_resize = cv2.resize(img,(int(width*0.5),int(height*0.5)),interpolation=cv2.INTER_CUBIC)#cv2.namedWindow('img',0)#cv2.imshow("img",img_resize)print("img_reisze shape:{}".format(np.shape(img_resize)))#将图片转为灰度图img_gray = cv2.cvtColor(img_resize,cv2.COLOR_RGB2GRAY)#cv2.namedWindow('img_gray',0)#cv2.imshow("img_gray",img_gray)cv2.imwrite('Grey_11.jpg', img_gray)print("img_gray shape:{}".format(np.shape(img_gray)))cv2.waitKey()

二值化处理

二值化是图像分割的一种最简单的方法,二值化可以把灰度图像转换成二值图像。把大于某个临界灰度值(阈值)的像素灰度设为灰度极大值(255),把小于这个值的像素灰度设为灰度极小值(0),从而更有利于做图像处理判别。
二值化分为固定阈值和自适应阈值,本题采用自适应赋值方法,借助Opencv编程得到二值化图像如下图


二值化代码

import cv2 as cv
import numpy as np
# 根据选定的方法自动寻找阈值
src = cv.imread('Grey_20.jpg')
def threshold_demo(image):# 灰度图像gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)# 二值图像ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)print('threshold value %s' % ret)cv.imshow('binary', binary)# 局部阈值
def local_threshold(image):gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)# blockSize 必须是奇数,下面设为25, 比均值大10(自己设置)就设置为黑色或者白色,在10之内的设置为另一个颜色dst = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)#cv.imshow('binary', dst) cv.imwrite('Grey_20.jpg', dst)
# 自适应阈值
def custom_threshold(image):gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)h, w = gray.shape[:2]m = np.reshape(gray, [1, w*h])# 均值mean = m.sum() / (w*h)print('mean:', mean)ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)cv.imshow('binary', binary)
# 手动设定阈值
def threshold_demo_1(image):gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_TRUNC)print('threshold value %s' % ret)cv.imshow('binary', binary) #cv.namedWindow('input image', cv.WINDOW_AUTOSIZE)
#cv.imshow('input image', src)
local_threshold(src)
cv.waitKey(0)
cv.destroyAllWindows()

Canny边缘检测

Canny边缘检测是从不同视觉对象中提取有用的结构信息并大大减少要处理的数据量的一种技术,其边缘检测算法处理流程主要有包括:
1. 使用高斯滤波器,以平滑图像,滤除噪声
2. 计算图像中每个像素点的梯度强度和方向。
3. 应用非极大值抑制,以消除边缘检测带来的杂散响应。
4. 应用双阈值检测来确定真实的和潜在的边缘。
5. 通过抑制孤立的弱边缘最终完成边缘检测。
其中,阈值的选取是否得决定着图像是否具有连续性,本文采用动态赋予阈值的方法,通过Opencv编程得到Canny边缘检测结果。

代码如下

import cv2
import numpy as np
def CannyThreshold(lowThreshold):detected_edges = cv2.GaussianBlur(gray,(3,3),0)detected_edges = cv2.Canny(detected_edges,lowThreshold,lowThreshold*ratio,apertureSize = kernel_size)dst = cv2.bitwise_and(img,img,mask = detected_edges)  # just add some colours to edges from original image.cv2.imshow('canny demo',dst)cv2.imwrite('Canny_20.jpg', dst)
lowThreshold = 0
max_lowThreshold = 100
ratio = 3
kernel_size = 3
img = cv2.imread('Grey_20.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.namedWindow('canny demo')
cv2.createTrackbar('Min threshold','canny demo',lowThreshold, max_lowThreshold, CannyThreshold)
CannyThreshold(0)  # initialization
if cv2.waitKey(0) == 27:cv2.destroyAllWindows()

模型的求解

数字图像处理过程始终能保持图像的再现,能够将我们所需要测量的区域加强并突显出来。
为便于计算与记录,本文将处理过的21组图像数据进行编排,生成excel表格(附录九),将杆高与影长数据带入问题二、三的数学模型进行求解,可得到附件四中的具体地理位置。

参考文献:

【1】张宇.数字图像梯形畸变校正算法研究与视频实时校正应用[D].安徽:安徽大学,2014:4-12
【2】张宇,张春燕,陈笋.基于OpenCV的视频图像梯形畸变实时校正方法[D].安徽:安徽大学科学学院,2013:43-47
【3】Daetalus.OpenCV-Python教程(8、Canny边缘检测)[Z].@CSDN,2013.
【4】The_Matrix_.图像透视变换原理及实现[Z].@CSDN,2018.

作者的话:

本文所用全部程序与图片均为自制,转载请注明出处,不胜感激。

基于Visual studio+Opencv+Python的透视变换、图像处理(灰度化、二值化、Canny边缘检测)模型——以2015数学建模A题太阳影子定位为例相关推荐

  1. Java图像处理:灰度、二值化、浮雕、去色、反向、怀旧、放大镜等

    图像是由一个个像素点组合而成,图像处理本身实际上是遍历图像的像素点,对像素点的RGB值进行更改,以达到图像处理的目的. 接下来,我们主要介绍一下图片转化为二维像素点数组的方法以及部分图像处理如灰度.二 ...

  2. 计算机视觉基础-图像处理(图像分割/二值化)cpp+python

    5.1 简介 该部分的学习内容是对经典的阈值分割算法进行回顾,图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单.计算量小.性能较稳定而成为图像分割中最基本和应用最广泛的分割技术.它特别适用 ...

  3. 计算机视觉基础-图像处理 Task05 图像分割/二值化

    文章目录 OSTU二值化 自适应阈值 函数实现 OSTU二值化 自适应阈值 图像阈值化分割是一种传统的最常用的图像分割方法,因其实现简单.计算量小.性能较稳定而成为图像分割中最基本和应用最广泛的分割技 ...

  4. 计算机视觉基础-图像处理之图像分割/二值化

    阈值分割基本概念 二值化就是让图像的像素点矩阵中的每个像素点的灰度值为0(黑色)或者255(白色),也就是让整个图像呈现只有黑和白的效果,在灰度化的图像中灰度值的范围为0~255,在二值化后的图像中的 ...

  5. 【OpenCV 4开发详解】图像二值化

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  6. opencv 车牌识别---新能源车牌处理(二值化后按位取反)

    场景: 在对车牌号进行识别时,不能识别出新能源车牌的车牌号. 问题原因:   因为我们的识别模板都是黑底白字,新能源的车牌进行二值化处理后都是白地黑字. 模板: 新能源车牌原图(部分): 新能源车牌二 ...

  7. 图像处理中的二值化和灰度化

    图像的灰度化: 灰度是指只含亮度信息,不含色彩信息的图像.黑白照片就是灰度图,特点是亮度由暗到明,变化是连续的.要表示灰度图,就需要把亮度值进行量化 使用灰度图的好处: ① RGB的值都一样. ② 图 ...

  8. MATLAB算法实战应用案例精讲-【图像处理】数字图像二值化(附Java、python、matlab、C++和R语言代码实现)

    目录 前言 知识储备 图像平滑 像素点 图像的灰度化 灰度处理的方法

  9. 利用Python实现图像的二值化

    目录 1.全局阈值法 1.1主要函数: 1.2全局阈值的代码实现 1.3特点 2.自适应阈值法 2.1主要函数: 2.2实现代码: 2.3特点: 3.OTSU二值化(最大类间方差法) 3.1实现代码: ...

  10. linux 正点原子ov5640_【正点原子FPGA连载】第二十六章基于OV5640的二值化实验-摘自【正点原子】领航者 ZYNQ 之嵌入式开发指南 (amobbs.com 阿莫电子论坛)...

    本帖最后由 正点原子 于 2020-10-26 16:21 编辑 QQ群头像.png (1.78 KB) 2020-10-24 10:50 上传5)关注正点原子公众号,获取最新资料 100846rel ...

最新文章

  1. 计算机书籍- 聊天机器人技术原理与应用
  2. 修改MySQL日志文件位置
  3. Linux下tmp文件夹的文件自动删除的问题(转)
  4. mybatis配置文件形式
  5. BFS HDOJ 2102 A计划
  6. 主要矛盾和次要矛盾_次要GC,主要GC与完整GC
  7. SpringBoot实战(五)之Thymeleaf
  8. MySQL 索引分析除了 EXPLAIN 还有什么方法?
  9. 产品经理学SQL—前言
  10. 2019 年最好用的 7 款数据库监控工具
  11. mysql内外三种连接_mysql之内连接,外连接(左连接,右连接),union,union all的区别...
  12. yum更新指定的软件
  13. 23. Django进阶:Django发送邮件
  14. php html ubb,PHP写的UBB代码转换HTML代码
  15. 《企业IT架构转型之道-阿里巴巴中台战略思想与架构实战》读书笔记
  16. visio 2003 怎么样画括号
  17. MIL-STD-810G湿热试验,权威美军标环境试验报告
  18. 怎样将exe打包成服务运行
  19. android矢量图 内存大,Android内存控制小技巧-使用矢量图来节省你的内存并简化你的开发。...
  20. 录屏软件哪个好?快来试试这几款吧!

热门文章

  1. 移动端跨平台框架分析
  2. 2019最新版Eclipse下载与安装
  3. H5页面在自己APP中图标显示正常,接入钉钉请求.woff图标字体报错
  4. 测试开发面试-技术题持续累积
  5. CDMA2000中的Walsh码,PN码,短码序列的初相位偏置(PN OFFSET)之間的差別與關係(1)
  6. 学生管理系统(JAVA后台简约版)
  7. Au 音频效果参考:特殊效果
  8. Java 根据 Map 的 key 的 ASCII 码从小到大排序
  9. Windows10桌面美化——打造简洁高效美观桌面
  10. autocad插件无法加载无法运行的解决办法