读取图片信息

  • 显示图片
  • 查看RGB参数
  • 查看图片详细信息
  • 获取图片信息
  • 最终整合


显示图片

显示结果没有原图清晰

from skimage import io
import matplotlib.pyplot as plt

img=io.imread('F:\Vue\kool.jpg')
io.imshow(img)
plt.show()

查看RGB参数

图片的像素可以右击点【属性】,选择【详细信息】就可以看图片的具体信息。
我用手机拍的一张照片,发原图到电脑上。用这种方法可以查看拍摄时间,拍摄地经纬度,手机型号等。

from skimage import io
import matplotlib.pyplot as plt

img=io.imread('F:\Vue\img\kool.jpg')

print(img.shape)
for i in img[0]:
    print(i)

'''
第一个打印结果:(3059, 2448, 3)
我的kool.jpg文件,分辨率是2448x3059。
所以img.shape 的输出结果代表图片高3059像素,宽2448像素,每个像素有3个参数。这里的参数是RGB数值,即构成这个像素的三个RGB数值
所以这张图片可以看作是一张3059行2448列的表,每个表格里都有三个数



第二个循环打印结果如下,我这里截取了前五个:
[218 217 215]
[219 218 216]
[220 219 217]
[220 219 217]
[220 219 217]
...		...

len(img[0])=2448,上面这些就是第一行里面的像素参数
第一行的第一个像素点,R(red)218、G(green)217、B(blue)215
第一行的第二个像素点,R219、G218、B216	......

'''

查看图片详细信息

import exifread

def getImgInfo(img_path):
    img_read = open(img_path, 'rb')
    img_exif = exifread.process_file(img_read)
    if img_exif:
        for item in img_exif:
            print("{0}:{1}".format(item,img_exif[item]))
    else:
        print("图像信息为空,可能是上传的不是原图")

if __name__ == '__main__':
    img_path = 'F:\Vue\img\qq_20210916_190641.jpg'
    getImgInfo(img_path)

大多数图片都能读出来信息来,除非这张图片很“干净”或者不是原图。

获取图片信息

import exifread
import pprint

def getImgInfo(img_path):
    img_read = open(img_path, 'rb')
    img_exif = exifread.process_file(img_read)
    imgInfo = {}
    if img_exif:

        # for item in img_exif:
        #     print("{0}:{1}".format(item,img_exif[item]))

        imgInfo['图片宽度'] = str(img_exif['Image ImageWidth'])
        imgInfo['图片高度'] = str(img_exif['Image ImageLength'])

        imgInfo['手机品牌'] = str(img_exif['Image Make'])
        imgInfo['手机型号'] = str(img_exif['Image Model'])
        imgInfo['手机版本号'] = str(img_exif['Image Software'])
        imgInfo['拍摄时间'] = str(img_exif['Image DateTime'])

        imgInfo['纬度方向'] = str(img_exif['GPS GPSLatitudeRef'])

        lat = str(img_exif["GPS GPSLatitude"])[1: -1].replace("/", ",").split(",")
        imgInfo["纬度"] = float(lat[0]) + float(lat[1]) / 60 + float(lat[2]) / float(lat[3]) / 3600

        imgInfo['经度方向'] = str(img_exif['GPS GPSLongitudeRef'])
        lng = str(img_exif["GPS GPSLongitude"])[1: -1].replace("/", ",").split(",")
        imgInfo["经度"] = float(lng[0]) + float(lng[1]) / 60 + float(lng[2]) / float(lng[3]) / 3600

        # 还有一个GPS GPSAltitudeRef参数, 但不知道它的数值是啥意思
        imgInfo['高度'] = str(img_exif['GPS GPSAltitude'])

    return imgInfo


if __name__ == '__main__':
    img_path = 'F:\Vue\img\qq_20210916_190641.jpg'
    imgInfo = getImgInfo(img_path)

    if imgInfo== {} :
        print("图像信息为空,可能是上传的不是原图")
    else:
        pprint.pprint(imgInfo)

得出坐标后可以用一个在线工具查看位置。 但在转换时要选择原始GPS属性,因为其他的会有偏差。其他几个我都做了对比,还原度最高的那个就是GPS属性,百度高德都不太准,毕竟自己拍的照片还是知道位置在哪的。
最终整合

接下来是使用高德提供的API来直接输出结果,有兴趣的可以研究一下怎么把偏差给修正。
这里是需要先在高德开放平台上申请一个 Web 服务的应用,获得一个秘钥Key 用于逆地理编码 API。

import exifread
import pprint
import requests
import json
import math


x_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626  # π
a = 6378245.0  # 长半轴
ee = 0.00669342162296594323  # 扁率



def wgs84togcj02(lng, lat):
    """
    WGS84转GCJ02(火星坐标系)
    :param lng:WGS84坐标系的经度
    :param lat:WGS84坐标系的纬度
    :return:
    """
    if out_of_china(lng, lat):  # 判断是否在国内
        return lng, lat
    dlat = transformlat(lng - 105.0, lat - 35.0)
    dlng = transformlng(lng - 105.0, lat - 35.0)
    radlat = lat / 180.0 * pi
    magic = math.sin(radlat)
    magic = 1 - ee * magic * magic
    sqrtmagic = math.sqrt(magic)
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
    dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
    mglat = lat + dlat
    mglng = lng + dlng
    return [mglng, mglat]


def gcj02towgs84(lng, lat):
    """
    GCJ02(火星坐标系)转GPS84
    :param lng:火星坐标系的经度
    :param lat:火星坐标系纬度
    :return:
    """
    if out_of_china(lng, lat):
        return lng, lat
    dlat = transformlat(lng - 105.0, lat - 35.0)
    dlng = transformlng(lng - 105.0, lat - 35.0)
    radlat = lat / 180.0 * pi
    magic = math.sin(radlat)
    magic = 1 - ee * magic * magic
    sqrtmagic = math.sqrt(magic)
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
    dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
    mglat = lat + dlat
    mglng = lng + dlng
    return [lng * 2 - mglng, lat * 2 - mglat]


def transformlat(lng, lat):
    ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
        0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
    ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
            math.sin(2.0 * lng * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(lat * pi) + 40.0 *
            math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
    ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *
            math.sin(lat * pi / 30.0)) * 2.0 / 3.0
    return ret


def transformlng(lng, lat):
    ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
        0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
    ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
            math.sin(2.0 * lng * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(lng * pi) + 40.0 *
            math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
    ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *
            math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
    return ret
    

def out_of_china(lng, lat):
    """
    判断是否在国内,不在国内不做偏移
    :param lng:
    :param lat:
    :return:
    """
    if lng < 72.004 or lng > 137.8347:
        return True
    if lat < 0.8293 or lat > 55.8271:
        return True
    return False



# 获取图片信息
def getImgInfo(img_path):
    img_read = open(img_path, 'rb')
    img_exif = exifread.process_file(img_read)
    imgInfo = {}
    if img_exif:
        imgInfo['图片宽度'] = str(img_exif['Image ImageWidth'])
        imgInfo['图片高度'] = str(img_exif['Image ImageLength'])

        imgInfo['手机品牌'] = str(img_exif['Image Make'])
        imgInfo['手机型号'] = str(img_exif['Image Model'])
        imgInfo['手机版本号'] = str(img_exif['Image Software'])
        imgInfo['拍摄时间'] = str(img_exif['Image DateTime'])

        imgInfo['纬度方向'] = str(img_exif['GPS GPSLatitudeRef'])
        lat = str(img_exif["GPS GPSLatitude"])[1: -1].replace("/", ",").split(",")
        imgInfo["纬度"] = float(lat[0]) + float(lat[1]) / 60 + float(lat[2]) / float(lat[3]) / 3600

        imgInfo['经度方向'] = str(img_exif['GPS GPSLongitudeRef'])
        lng = str(img_exif["GPS GPSLongitude"])[1: -1].replace("/", ",").split(",")
        imgInfo["经度"] = float(lng[0]) + float(lng[1]) / 60 + float(lng[2]) / float(lng[3]) / 3600
        # 还有一个GPS GPSAltitudeRef参数, 但不知道它的数值是啥意思
        imgInfo['高度'] = str(img_exif['GPS GPSAltitude'])

    return imgInfo



# 获取地址信息
def getAddress(imgInfo):
    if imgInfo:
        # 高德API只能识别到小数点后的6位,但好像它会自动将多余的裁掉
        # print("%.6f" % imgInfo["经度"])

        latitude = imgInfo["纬度"]
        longitude = imgInfo["经度"]

        # 注意:由于gps获取的坐标在国内高德等主流地图上逆编码不够精确,这里需要转换为火星坐标系
        # WGS84转GCJ02(火星坐标系)
        mglng, mglat = wgs84togcj02(longitude, latitude)

        url = 'https://restapi.amap.com/v3/geocode/regeo?key={}&location={}'  # 详见高德逆解析地理API文档
        location = '{},{}'.format(mglng, mglat)
        api_key = '将你的Key粘贴到这里'  
        resp = requests.get(url.format(api_key, location))

        data = json.loads(resp.text)
        address = data.get('regeocode').get('formatted_address')
        return data,address

    else:
        return 0,0


if __name__ == '__main__':
    img_path = 'F:\Vue\img\qq_20210916_190641.jpg'
    imgInfo = getImgInfo(img_path)
    data, address = getAddress(imgInfo)

    if imgInfo == {} :
        print("图像信息为空,可能是上传的不是原图")
    else:
        pprint.pprint(imgInfo)
        print('---------------------------')
        print(f"拍摄地址:{address}")