电脑里的照片如何归类整理?

2019-09-11 09:05:51 +08:00
 cshlxm
相机和 iphone 拍了很多照片,之前备份都是 windows 照片应用导入是按照月份分的,也有很多没有按照月份堆在一个文件夹下,现在几万图和视频(有 jpg、HEIC、HEVC、MOV、mp4、cr2 等等),分布在各个盘,一直想整理下,写了个 python 脚本用 md5 摘要把重复的图片、视频先删了,下一步想还没想好该怎么办?
各位大佬,有什么好的建议,比如好用的软件,或者怎么归类比较适合?
9378 次点击
所在节点    问与答
34 条回复
jaylong
2019-09-11 10:12:04 +08:00
@pilgrim_kevin 不会编程 等你的代码了 到时候就在此贴回复吧 记得 @我一下 谢谢啦
pilgrim_kevin
2019-09-11 10:12:13 +08:00
@cshlxm 哦,我没注意过 iphone 的问题,可能我的 iPhone 老一点,没注意有这个问题。
pilgrim_kevin
2019-09-11 10:13:40 +08:00
@jaylong 好。
chztv
2019-09-11 10:44:38 +08:00
@cshlxm 有时间的话,我觉得本地照片只能自己手动整理,印象里还没有哪个软件能完全代替人手。Adobe Bridge、Lightroom 之类的,还是需要手工整理文件夹,但如果是摄影发烧友,这二款肯定是必需的。
没有时间的话又不想上云的,我也想知道有啥办法,毕竟我自己也是从人手本地整理过渡到了云相册,毕竟当你的照片有 6 位数以上时,整理太费时间了,先在 Google Photos 上面把部分有用的照片整理成相册,然后打包下载相册存到 NAS 上。其实主要是看中了 Google Photos 的人工智能人脸识别,能把所有和小朋友的有关的照片全部标注成一个相册。
hensy
2019-09-11 11:15:16 +08:00
每次看到这样的帖子都忍不住要安利一下这个 APP:时光相册。连接 WIFI 自动备份,有人脸识别,支持分人物、地点、事物等自动归类,好用得一批。。
cskeleton
2019-09-11 11:57:39 +08:00
个人还是习惯手动整理,按年建文件夹,年以下就按事件建文件夹,比如我出去玩了一趟,就会按这种格式建一个文件夹 20190511_Chongqing,里面再分俩,raw 和 output,raw 下面可能会再按设备分,例如不同的相机和手机,output 可能会放这次事件别人拍的照片。不过我用手机拍得少,基本上一年一个手机相册的子文件夹就够了,如果手机拍的也属于某个事件,那也归类进去。

这样找起来也比较容易,我会先回忆我是在什么时候、哪次旅游、哪个活动、谁拍过某张照片。备份就是 GoodSync 定时同步到另一块硬盘,也不需要 RAID。后面计划把新的照片从身边这台星际蜗牛也定时同步回老家的 Gen8 上去做个异地备份。
JRay
2019-09-11 14:33:26 +08:00
@cshlxm LR 的照片管理功能很强大
akimotofeng996
2019-09-11 17:24:32 +08:00
上传到某云,利用云服务只能分类,还能从相似照片中取优选,节省空间
manxiaqu
2019-09-12 14:16:23 +08:00
ptsa
2019-09-13 21:38:27 +08:00
@manxiaqu 还不算完善 关注下
Huangenius
2019-09-16 03:46:32 +08:00
推荐一个个人觉得很好用的软件 Zoner Photo Studio X,比 Lr 对位置信息兼容更好,比 Picasa 整理大量图片有优势,本人 15 万左右张的照片可以按位置、时间、标签 等等分类(暂无人脸识别),支持各种格式包括 HEIC,没有 Google photos 的搜索引擎是个很大缺陷,管理本地文件还是很方便的。
pilgrim_kevin
2019-10-18 09:21:40 +08:00
@jaylong

src/handler_photo_by_date.py

#!/usr/bin/python
# -*- coding:utf-8 -*-
__author__ = 'Barry'

from PIL import Image
from PIL.ExifTags import TAGS
from datetime import datetime
from hashlib import md5
import time
import os
import shutil
import fnmatch
import random

global Count

def IterFindFiles(path, fnexp):
for root, dirs, files in os.walk(path):
for filename in fnmatch.filter(files, fnexp):
yield os.path.join(root, filename)

def GetPicPath():
pic_full_path = []
if os.path.isdir(input_path):
for i in os.listdir(input_path):
sub_dir = input_path + '/' + i
if os.path.isdir(sub_dir):
for n in os.listdir(sub_dir):
pic_full_path.append(sub_dir + '/' + n)
return pic_full_path


def print_all_know_exif_tags():
for k in sorted(TAGS):
print k, TAGS[k]

def FormatTime(date):
try:
ts = time.mktime(time.strptime(date,'%Y:%m:%d %H:%M:%S'))
return time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(ts))
except Exception, e:
return False

def TrimTime(mtime):
ts = time.mktime(time.strptime(mtime,'%Y-%m-%d %H:%M:%S'))
return time.strftime('%Y%m%d',time.localtime(ts))

def TrimTime2(mtime):
ts = time.mktime(time.strptime(mtime,'%Y-%m-%d %H:%M:%S'))
return time.strftime('%Y%m%d-%H%M%S',time.localtime(ts))

def GenMd5(filename):
file_tmp = open(filename,'rb')
md5_value = md5(file_tmp.read())
file_tmp.close()
return md5_value.hexdigest()

def GetPicExif():
pic_date = {}
#pic_path = GetPicPath()
for filename in IterFindFiles(input_path,fnexp):
mtime = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(os.stat(filename).st_mtime))
try:
img = Image.open(filename)
except Exception, e:
print filename,"skipping due to ",e
try:
exif_data = img._getexif()
except Exception, e:
print filename,"skipping due to ",e
finally:
if exif_data:
if exif_data.has_key(36867):
pic_date[filename] = FormatTime(exif_data[36867]) and FormatTime(exif_data[36867]) or mtime
elif exif_data.has_key(36868):
pic_date[filename] = FormatTime(exif_data[36868]) and FormatTime(exif_data[36868]) or mtime
elif exif_data.has_key(306):
pic_date[filename] = FormatTime(exif_data[306]) and FormatTime(exif_data[306]) or mtime
else:
pic_date[filename] = mtime
else:
pic_date[filename] = mtime

print filename, pic_date[filename]

return pic_date

def ArchivePic():
pic_date = GetPicExif()
Count = 0
new_dir_file_md5_list = []
for pic,mtime in pic_date.items():
std_out = "\033[1;33mAdd new picture \033[1;31m%s\033[0m\033[1;33m to dest path:%s\033[0m"%(os.path.split(pic)[1],output_path)
new_dir = "%s/%s"%(output_path,TrimTime(mtime))
if not os.path.exists(new_dir):
os.mkdir(new_dir)
new_file_name = '%s-%s%s'%(pic_prefix,TrimTime2(mtime),pic_suffix)
new_file_path = '%s/%s'%(new_dir,new_file_name)

print "processing", pic, "to", new_file_name

if not os.path.exists(new_file_path):
try:
if os.listdir(new_dir):
for i in os.listdir(new_dir):
hashvalue = GenMd5(os.path.join(new_dir,i))
new_dir_file_md5_list.append(hashvalue)
if GenMd5(pic) not in new_dir_file_md5_list:
shutil.move(pic,new_file_path)
#shutil.copy2(pic,new_file_path)
#os.remove(pic)
Count+=1
print Count, std_out
else:
shutil.move(pic,new_file_path)
#shutil.copy2(pic,new_file_path)
#os.remove(pic)
Count+=1
print Count, std_out
except Exception, e:
print e
else:
while True:
new_file_name = '%s-%s_%s'%(pic_prefix,TrimTime2(mtime),pic_suffix)
if new_file_name not in os.listdir(new_dir):
break
else:
continue
new_file_path = '%s/%s'%(new_dir,new_file_name)
for i in os.listdir(new_dir):
hashvalue = GenMd5(os.path.join(new_dir,i))
new_dir_file_md5_list.append(hashvalue)
if GenMd5(pic) not in new_dir_file_md5_list:
try:
shutil.move(pic,new_file_path)
#shutil.copy2(pic,new_file_path)
#os.remove(pic)
Count+=1
print Count, std_out
except Exception, e:
print e
else:
os.remove(pic)

return


if __name__ == "__main__":
input_path = r"/home/xxx/Camera"
output_path = r"/home/xxx/New"
fnexp = "*.jpg"
pic_suffix = ".jpg" #如果查找的是 jpg 文件,那文件后缀名也要匹配
pic_prefix = "IMG"
birth_day = '20191018'
if not os.path.exists(output_path):
os.mkdir(output_path)
if not os.path.exists(input_path):
print "some of path not found!"
else:
ArchivePic()
#print_all_know_exif_tags()
pilgrim_kevin
2019-10-18 09:24:13 +08:00
不好意思不知道如何保持格式贴代码, 楼上有耐心的话自己整理下缩进,python 是缩进敏感的
higkoo
2020-02-29 19:50:54 +08:00
刚刚用 Shell 整理了近 5 万张 10 多年的照片,供参考:
https://my.oschina.net/higkoo/blog/3179534
(视频文件和 HEIC 格式的图片 待处理)

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/599858

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX