Python处理图片生成天际线(2024.1.29)

1、天际线简介

        天际线SkyLine)顾名思义就是天空与地面的边界线,人站在不同的高度,会看到不同的景色和地平线,天空与地面建筑物分离的标记线,不得不说,每天抬头仰望天空,相信大家都可以看到,它的的确确客观存在,美丽值得欣赏。

2、Python代码

#-*- coding:utf-8 -*-
import sys
from os.path import exists
import cv2
import numpy as np

def getImage(height, width, channels):
    image = np.zeros([height, width, 3], np.uint8) # 三通道顺序是BGR
    # 三层循环逐个修改像素点
    for row in range(height):
        for col in range(width):
                for c in range(channels):
                    image[row, col, c] = 0
    return image

def isWhite(pixel_value, threshold): #阈值可以取10、20、30、50、100
    res = False
    if pixel_value[0] > threshold and pixel_value[1] > threshold and pixel_value[2] > threshold: # 10、10、10 50、50、50 这里是天空和地面楼山的分界线,需要调参
        res = True
    return res

def isPureWhite(pixel_value):
    res = False
    if pixel_value[0] == 255 and pixel_value[1] == 255 and pixel_value[2] == 255: # >3|>3|>3 10、10、10
        res = True
    return res

def getRowNumberSpecificCol(image, col):
    res_row = -1
    height, width = image.shape[0:2]
    if col >= 0 and col < width:
        for row in range(0, height):
            pv = image[row][col]
            if(pv[0] > 0 and pv[1] > 0 and pv[2] >0):
                res_row = row
                break
    return res_row

def getEnhancedEdgeImageFromEdgeImage(edge_Image):
    edge_SrcImage = edge_Image
    height, width = edge_SrcImage.shape[0:2]
    for col in range(1, width):
        for row in range(0, height):
            pixel_value = edge_SrcImage[row][col]  # 计算红绿蓝三波段的平均值
            if isPureWhite(pixel_value):
                r_last = getRowNumberSpecificCol(edge_SrcImage, col - 1)
                if r_last:
                    if row > r_last:
                        minR, maxR = r_last, row
                        for k in range(minR, maxR):
                            edge_SrcImage[k][col - 1][0] = 255
                            edge_SrcImage[k][col - 1][1] = 255
                            edge_SrcImage[k][col - 1][2] = 255
                    else:
                        minR, maxR = row, r_last
                        for k in range(minR, maxR):
                            edge_SrcImage[k][col][0] = 255
                            edge_SrcImage[k][col][1] = 255
                            edge_SrcImage[k][col][2] = 255
    # cv2.imshow("Enhanced-edge-image", edge_SrcImage)
    return edge_SrcImage

def getFileExtensionname(filename):
    res = ".png"
    dot_index = -1
    for i in range(len(filename), 0):
        if filename[i] == '.':
            dot_index = i
            break
    if dot_index != -1:
        res = filename[dot_index: len(filename)-1]
    return res

if __name__ == '__main__':
    origin_pic_filename = "D:/test.png"
    sky_ground_threshold = 30
    isDownSampling = False
    if (len(sys.argv) == 1):
        print(sys.argv[0])
        origin_pic_filename = ""
    elif(len(sys.argv) == 2):
        origin_pic_filename = str(sys.argv[1])
    elif(len(sys.argv) == 3):
        origin_pic_filename = str(sys.argv[1])
        sky_ground_threshold = int(sys.argv[2])
    elif (len(sys.argv) == 4):
        origin_pic_filename = str(sys.argv[1])
        sky_ground_threshold = int(sys.argv[2])
        if(int(sys.argv[3]) == 1):
            isDownSampling = True
    if origin_pic_filename != "" and sky_ground_threshold > 0:
        print(("输入图片文件名为:{0}").format(origin_pic_filename))
        print(("天空地面分界灰度阈值为:{0}").format(sky_ground_threshold))
        suffix_name = getFileExtensionname(origin_pic_filename)
        print(("后缀名为:{0}").format(suffix_name))

        srcImage = cv2.imread(origin_pic_filename)
        inputSrcImage = srcImage
        if isDownSampling:
            inputSrcImage = cv2.pyrDown(inputSrcImage)
        height, width = inputSrcImage.shape[0:2]
        print(("高度:{0}, 宽度:{1}").format(height, width))
        cv2.namedWindow('downsampling-image', cv2.WINDOW_AUTOSIZE)
        cv2.imshow("downsampling-image", inputSrcImage)
        Sobelx = cv2.Sobel(inputSrcImage, cv2.CV_64F, 1, 0)
        Sobely = cv2.Sobel(inputSrcImage, cv2.CV_64F, 0, 1)
        Sobelx = cv2.convertScaleAbs(Sobelx)
        Sobely = cv2.convertScaleAbs(Sobely)
        # cv2.imshow("sobel-x-Abs", Sobelx)
        # cv2.imshow("sobel-y-Abs", Sobely)
        Sobelxy = cv2.addWeighted(Sobelx, 0.5, Sobely, 0.5, 0)
        cv2.namedWindow('sobel-xy', cv2.WINDOW_AUTOSIZE)
        cv2.imshow('sobel-xy', Sobelxy)
        edgeImage = getImage(height, width, 3)
        for col in range(0, width):
            for row in range(0, height):
                pixel_value = Sobelxy[row][col]  # 计算红绿蓝三波段的平均值
                if isWhite(pixel_value, sky_ground_threshold):
                    edgeImage[row][col][0] = 255
                    edgeImage[row][col][1] = 255
                    edgeImage[row][col][2] = 255
                    break
        cv2.namedWindow('edge-image', cv2.WINDOW_AUTOSIZE)
        cv2.imshow('edge-image', edgeImage)
        cv2.imwrite(origin_pic_filename.replace(suffix_name, "-ZGetEdge.png"), edgeImage)
        enhanced_edgeImage = getEnhancedEdgeImageFromEdgeImage(edgeImage)
        cv2.namedWindow('enhanced-edge-image', cv2.WINDOW_AUTOSIZE)
        cv2.imshow('enhanced-edge-image', enhanced_edgeImage)
        cv2.imwrite(origin_pic_filename.replace(suffix_name, "-EnhancedEdge.png"), enhanced_edgeImage)

        for col in range(0, width):
            for row in range(0, height):
                pixel_value = enhanced_edgeImage[row][col]  # 计算红绿蓝三波段的平均值
                if isPureWhite(pixel_value):
                    if row+2 < height:
                        inputSrcImage[row+2][col][0] = 0
                        inputSrcImage[row+2][col][1] = 0
                        inputSrcImage[row+2][col][2] = 255
                    else:
                        inputSrcImage[row][col][0] = 0
                        inputSrcImage[row][col][1] = 0
                        inputSrcImage[row][col][2] = 255
                    # inputSrcImage[row][col][0] = 0
                    # inputSrcImage[row][col][1] = 0
                    # inputSrcImage[row][col][2] = 255
                    # break #最开始从每列遍历从上到下找第一个分界点就停止才用break

        cv2.namedWindow('RedEdge-image', cv2.WINDOW_AUTOSIZE)
        cv2.imshow('RedEdge-image', inputSrcImage)
        cv2.imwrite(origin_pic_filename.replace(suffix_name, "-RedEdge.png"), inputSrcImage)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
        print('Success!')
        cv2.waitKey()
        cv2.destroyAllWindows()

3、运行结果

        test.jpg下载

3.1 非下采样+边缘检测

python GetSkyLine.py test.jpg  100
原始图片
边缘点图片
边缘增强图片
sobel-xy处理后图片
downloadsampling图片
红色边缘叠加图片

3.2 下采样+边缘检测

python GetSkyLine.py test.jpg  50  1
原始图片
边缘点图片
边缘增强图片
downloadsampling图片
sobel-xy处理后图片
红色边缘叠加图片

4、小结

        在这个人世间,每个人都是独立的个体,身处浩荡洪流之中,难免身不由己,时而坚定,时而困惑,但我们还是应该永远相信美好的事情终将发生,要心怀一颗感恩的心,相信家人,相信自己,相信未来,坦然面对生活,接受平凡。

       关关难过关关过,前路漫漫亦灿灿

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

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

相关文章

窥探向量乘矩阵的存内计算原理—基于向量乘矩阵的存内计算

在当今计算领域中&#xff0c;存内计算技术凭借其出色的向量乘矩阵操作效能引起了广泛关注。本文将深入研究基于向量乘矩阵的存内计算原理&#xff0c;并探讨几个引人注目的代表性工作&#xff0c;如DPE、ISAAC、PRIME等&#xff0c;它们在神经网络和图计算应用中表现出色&…

三维模型设计新纪元:3D开发工具HOOPS在机械加工行业的应用与优势

在当今快速发展的科技时代&#xff0c;机械加工行业正经历着巨大的变革&#xff0c;而HOOPS技术正是其中一项重要的创新。HOOPS技术不仅仅是一种用于处理和可视化计算机辅助设计&#xff08;CAD&#xff09;数据的工具&#xff0c;更是机械加工领域中提升效率、优化设计的利器。…

SI3933 15k-125kHZ低频唤醒开发技术资料

SI3933完美兼容&#xff1a;AS3933.PAN3501,GC3933Si3933 是一款三通道的低功耗 ASK 接收机&#xff0c;可用于检测 15kHz-150kHz 低频载波频率的数字信号&#xff0c;并产生唤醒信号。内部集成的校验器用于检测 16 位或 32 位曼彻斯特编码的唤醒向量&#xff0c;且支持两次重复…

超声波自动气象站是什么?

TH-CQX12超声波自动气象站是一种利用超声波技术进行气象观测和数据采集的自动化设备。它能够实时监测温度、湿度、风速、风向、气压、雨量等多种气象要素&#xff0c;并通过无线传输方式将数据发送到数据中心进行分析和处理。 与传统气象站相比&#xff0c;超声波自动气象站具有…

申万宏源:证券低时延交易系统全链路自主可控创新实践 |论坛实录

由中科驭数主办的第二届证券基金行业先进计算技术大会暨2024低时延技术创新实践论坛&#xff08;上海站&#xff09;在上海举行。会上各位嘉宾深入的分享&#xff0c;吸引了不少行业同仁对本次会议干货内容的关注。特此&#xff0c;中科驭数整理部分演讲者发言实录&#xff0c;…

ARM汇编 2.arm常用指令

MOV 赋值操作 寄存器 < 寄存器/存储器/立即数 MOV{条件}{S} 目的寄存器&#xff0c;源操作数 没有S时指令不更新 CPSR 中条件标志位的值 立即数&#xff1a;由0-255之间的数据循环右移偶数位生成。(移动规则不用掌握) #0xfff不是立即数&#xff0c;而0x80000001是立即数 …

Mysql-ReadView + MVCC-RR 与 RC

实验准备 创建脚本 CREATE TABLE user (id int(11) NOT NULL AUTO_INCREMENT,name varchar(16) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,age int(11) NULL DEFAULT NULL,addr varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,PRIMARY …

3款最好用的tron钱包解读:TronLink,Ledger,Bitget钱包

电子钱包是用户连接到区块链网络的重要媒介。除了接收和发送功能外&#xff0c;它还可用于传输虚拟货币。它也是使用分散应用程序&#xff08;DApp&#xff09;的必要工具&#xff01;无论您是想在ON上使用以太坊&#xff0c;EOS还是任何DApp&#xff0c;您都必须先拥有钱包。因…

vxe-table表格合并行和虚拟滚动冲突

项目一直用的vxe-table 2.0版本&#xff0c;支持表格的虚拟滚动&#xff0c;最近要做表格合并行功能&#xff0c;虚拟滚动便失效了&#xff0c;强行虚拟滚动&#xff0c;合并行会有错行现象。 vxe-table2.0给出的解释是&#xff1a;合并行不能和虚拟滚动一起使用。 目前找到两种…

华为配置小型网络WLAN 的基本业务示例

配置小型网络WLAN基本业务示例 组网图形 图1 配置小型网络WLAN基本业务组网图 小型WLAN网络简介配置注意事项组网需求数据规划配置思路操作步骤配置文件 小型WLAN网络简介 本文介绍的WLAN网络是指利用频率为2.4GHz或5GHz的射频信号作为传输介质的无线局域网&#xff0c;相对于有…

【css】设置渐变阴影

css的属性中没有直接设置渐变阴影的&#xff0c;但是可以通过伪元素去实现。 .box-wrap{width: 100%;display: grid;place-content: center; } .box {width: 150px;height: 150px;background: #eee;border: 1px solid #585252;position: relative;transform: translate(0);/* …

论文阅读,Domain Specific ML Prefetcher for Accelerating Graph Analytics(一)

目录 一、Article:文献出处&#xff08;方便再次搜索&#xff09; &#xff08;1&#xff09;作者 &#xff08;2&#xff09;文献题目 &#xff08;3&#xff09;文献时间 &#xff08;4&#xff09;引用 二、Data:文献数据&#xff08;总结归纳&#xff0c;方便理解&am…

微调入门篇:大模型微调的理论学习

1、为什么大模型微调 之前在《大模型这块蛋糕,想吃吗》介绍了普通人如何搭上大模型这块列车, 其中有一个就是模型微调,这个也是未来很多IT公司需要发力的方向,以及在《垂直领域大模型的应用更亲民》中论述了为什么微调适合大家,以及微调有什么价值? 作为小程序猿在开始进行微…

Mac截图软件CleanShot X为什么不能识别文字?CleanShot X文字识别教程

好多朋友在使用CleanShot X for Mac截图软件过程中发现不能进行OCR文字识别&#xff1f;其实这是因为你没有给CleanShot X相应的权限导致的&#xff0c;具体操作如下&#xff1a; 第一步、打开&#xff0c;系统偏好设置-隐私与安全设置-完全磁盘访问权限 点击左下方➕ 在应用程…

能替代微软AD的国产化方案,搭建自主可控的身份管理体系

随着国产化替代步伐加速&#xff0c;以及企业出于信息安全建设的需要&#xff0c;越来越多的企业和组织开始考虑将现有的微软 Active Directory&#xff08;AD&#xff09;替换为国产化的LDAP身份目录服务&#xff08;也称统一身份认证和管理&#xff09;系统。本文将介绍一种国…

App测试中ios和Android有哪些区别呢?

App测试中&#xff0c;大家最常问到的问题就是&#xff1a;ios和 Android有什么区别呢&#xff1f; 在Android端&#xff0c;我们经常会使用 JavaScript、 HTML、 CSS等技术来编写一些简单的 UI界面。而 iOS端&#xff0c;我们经常会使用到 UI设计、界面布局、代码结构、 API等…

【经典项目】Java入门,实现斗地主小游戏

一、需求分析 实现斗地主游戏可以涉及以下几个关键步骤和思路&#xff1a; 游戏规则定义&#xff1a;首先&#xff0c;你需要明确斗地主游戏的规则&#xff0c;包括牌的花色和大小、玩家数量、发牌顺序、出牌规则、胜利条件等。 牌的表示和初始化&#xff1a;定义一套扑克牌的…

AtCoder Beginner Contest 338F - Negative Traveling Salesman【floyd+状态压缩dp】

原题链接&#xff1a;https://atcoder.jp/contests/abc338/tasks/abc338_f Time Limit: 6 sec / Memory Limit: 1024 MB Score: 500 points、 问题陈述 有一个有N个顶点和M条边的加权简单有向图。顶点的编号为 1 到 N&#xff0c;i/th 边的权重为 Wi​&#xff0c;从顶点 U…

十年创业记-01-草根搭上时代快车

十年创业的点点滴滴&#xff0c;记录起步、发展到壮大的过程&#xff0c;有失败的教训&#xff0c;有成功的经验&#xff0c;也有一些建议&#xff0c;与君共勉。 今年35岁&#xff0c;创业的第九年&#xff0c;坐标十八线小城市&#xff0c;软件外包行业。从2015年20万的营业额…

GWIT 和GWFI

关于燃烧的历史&#xff1a; -UL request needle flame (open fire) test to rate flammability per UL-94 Vxx UL 要求针焰&#xff08;明火&#xff09;试验以评定UL-94的易燃性。 - industry recognized that glowing wires ( caused by electrical overload) may put …