Python+OpenCV+图片旋转并用原底色填充新四角_python旋转图片任意角度 并填充-程序员宅基地

技术标签: python  

1.开始使用的是下面这种旋转方法:

def rotate(pic):
	img = cv2.imread(pic)   
	# img = Image.open(pic)
	# img = np.array(img)
	height, width = img.shape[:2]
	degree = 5
	# 旋转后的尺寸
	heightNew = int(width * fabs(sin(radians(degree))) + height * fabs(cos(radians(degree))))
	widthNew = int(height * fabs(sin(radians(degree))) + width * fabs(cos(radians(degree))))
	matRotation = cv2.getRotationMatrix2D((width / 2, height / 2), degree, 1)
	matRotation[0, 2] += (widthNew - width) / 2  
	matRotation[1, 2] += (heightNew - height) / 2  
	imgRotation = cv2.warpAffine(img, matRotation, (widthNew, heightNew), borderValue=(255, 255, 255))

 仿射变换之后,borderValue可以设置边界的颜色,设置成255,255,255之后,边界没有黑边,但是图像实际是没有填满的,感觉很突兀:

看到的效果:                                                             实际的效果:

                                

2.之后使用这种填充边界的方法:

def get_img_rot_broa(img, degree, filled_color=-1):
    """
    Desciption:
            Get img rotated a certain degree,
        and use some color to fill 4 corners of the new img.
    """
 
    # 获取旋转后4角的填充色
    if filled_color == -1:
        filled_color = mode([img[0, 0], img[0, -1],
                             img[-1, 0], img[-1, -1]]).mode[0]
    if np.array(filled_color).shape[0] == 2:
        if isinstance(filled_color, int):
            filled_color = (filled_color, filled_color, filled_color)
    else:
        filled_color = tuple([int(i) for i in filled_color])
 
    height, width = img.shape[:2]
 
    # 旋转后的尺寸
    height_new = int(width * fabs(sin(radians(degree))) +
                     height * fabs(cos(radians(degree))))
    width_new = int(height * fabs(sin(radians(degree))) +
                    width * fabs(cos(radians(degree))))
 
    mat_rotation = cv2.getRotationMatrix2D((width / 2, height / 2), degree, 1)
 
    mat_rotation[0, 2] += (width_new - width) / 2
    mat_rotation[1, 2] += (height_new - height) / 2
 
    # Pay attention to the type of elements of filler_color, which should be
    # the int in pure python, instead of those in numpy.
    img_rotated = cv2.warpAffine(img, mat_rotation, (width_new, height_new),
                                 borderValue=filled_color)
    # 填充四个角
    mask = np.zeros((height_new + 2, width_new + 2), np.uint8)
    mask[:] = 0
    seed_points = [(0, 0), (0, height_new - 1), (width_new - 1, 0),
                   (width_new - 1, height_new - 1)]
    for i in seed_points:
        cv2.floodFill(img_rotated, mask, i, filled_color)
 
    return img_rotated

if __name__=='__main__':
    pic=cv2.imread("test/contrast/ocr_4846387752.jpg")
    img_rotated=get_img_rot_broa(pic,degree=-5)
    cv2.imwrite('img_rotated.jpg',img_rotated)

虽然没有百分百的契合,但是也还行吧:

      

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_40446557/article/details/110185681

智能推荐

使用 arm-linux-androideabi-addr2line 工具定位 libunity.so 崩溃问题-程序员宅基地

文章浏览阅读710次,点赞13次,收藏7次。它的名称有点不同 - aarch64-linux-android-addr2line。尽管该实用程序的名称不包含单词arm,但它成功地解密了arm64-v8下的堆栈跟踪,并通常感知arm64-v8的字符。是 NDK 自带的调试工具,可以用来分析 so 崩溃时输出的的内存地址。之后就是通过 cmd 进入到这个路径。找到了 64 位所需的实用程序。_arm-linux-androideabi

javaweb-邮件发送_javaweb发送邮件-程序员宅基地

javaweb-邮件发送 摘要: 本文介绍了邮件传输协议(SMTP和POP3)以及电子邮件的发送和接收过程。还讨论了纯文本文件、带图片和附件的邮件发送方法,以及通过servlet方式注册邮箱和使用springboot框架发送邮件的实现。

element-ui table 设置表格滚动条位置_element table 滚动条位置-程序员宅基地

文章浏览阅读4.3k次,点赞6次,收藏11次。在切换不同页面时(被 keep-alive 缓存的组件间切换),页面中的element-ui table的滚动条位置没有停留在原来的位置。目前需要切换不同的页面返回来后,滚动条保持在原来的位置。_element table 滚动条位置

前端开发经验总结_属性值[session.getattribute("strpath")]引用["],在值内使用时必须-程序员宅基地

文章浏览阅读2.6k次。 我设置nowrap和不设置nowrap效果都一样。就是表格随着文字自动伸展,为什么? →回答问题:TD元素noWrap属性的行为与TD元素的width属性有关。 ◆如果未设置TD宽度,则noWrap属性是起作用的。◆如果设置了TD宽度,则noWrap属性是不起作用的。 http://www.blueidea.com/tech/web/2003/943.as_属性值[session.getattribute("strpath")]引用["],在值内使用时必须被转义。

JS如何把Object对象的数据输出到控制台中_前端怎么通过控制台查看字段取值-程序员宅基地

文章浏览阅读3.4k次,点赞2次,收藏3次。 前端时间在编写程序时遇到这样一个问题,即在前端页面通过一些js框架自带的异步请求返回的数据类型为Object数据类型,笔者根据网上查阅到的资料,找到以下这种简单的方式://把Object类型转为Json数据格式,再通过console命令在控制台中打印出来console.log("xhr的值为:"+JSON.st..._前端怎么通过控制台查看字段取值

8.cc.Button组件使用详解_cc button.start-程序员宅基地

文章浏览阅读556次。1. cc.Button添加按钮的方法 2种方式 (1)直接创建带Button组件的节点; (2) 先创建节点,再添加组件;按钮组件, 按钮是游戏中最常用的组件, 点击然后响应事件;按钮的过渡效果: 过渡: 普通状态, 鼠标滑动到物体上, 按下状态, 禁用状态 (1)没有过渡,只有响应事件; (2)颜色过渡, 过渡效果中使用颜色; (3)精灵..._cc button.start

随便推点

计算机专业游戏本推荐,2018高性价比游戏本推荐_游戏笔记本哪个好-太平洋电脑网...-程序员宅基地

文章浏览阅读245次。【PConline海选导购】晃眼间,秋风又起,让人振奋的开学季又要到来了!虽然说没有学习压力的暑假,在家着实悠哉,但想到回校后可以跟小伙伴们一起各种开黑吃鸡,是不是就感到很兴奋呢?说到“吃鸡”这种吃配置的游戏,就不得不说游戏本了,毕竟普通的笔记本电脑很难给我们带来畅快的游戏体验。而近年来游戏本市场俨然成为了各大厂商的必争之地,而随着开学季的到来,各大厂商更是推出了众多促销活动,下面就让我们一起来看..._计应专业游戏本

codePen按钮样式学习

看到codepen里面有的按钮搞得很炫酷,但其实也不是很难,就学习记录一下。

服务器维护中没法直播游戏,我的世界盒子显示维护中如何进入战堂服务器-程序员宅基地

文章浏览阅读408次。时间:2021-08-11编辑:hxh斗罗大陆魂师对决火雨队怎么搭配?火雨队是近期非常热门的一套阵容,不少玩家想了解该阵容,那么下面就让小编给大家带来斗罗大陆魂师对决火雨队阵容推荐,感兴趣的小伙伴们一起来看看吧。时间:2021-08-11编辑:hxh玩家在巅峰演武副本中不知道怎么打秦明,秦明的盾很厚不知道怎么破?那么下面就让小编给大家带来斗罗大陆魂师对决巅峰演武秦明破盾攻略,感兴趣的小伙伴们一起来...

GNU Radio之Schmidl & Cox OFDM synch.底层C++实现

在 GNU Radio OFDM 系统中,一个非常重要的环节是在接收端准确地同步和检测发送端发出的信号。这就是 Schmidl & Cox 同步算法发挥作用的地方。Schmidl & Cox 算法是一种用于 OFDM 信号的时间同步的技术。本文对其底层 C++ 源码进行学习记录。

项目开发规范

REST,表述性状态转换,他是一种软件架构风格使用URL定位资源,HTTP动词描述操作根据发出请求类型来区分操作此为风格,是约定方式,可以打破描述模块的功能通常使用复数,也就是加s的格式来描述,表示此类资源,而非单个资源。

3.8设计模式——State 状态模式(行为型)

允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。