Image Collections

Giulio Alessandrini, WRI

Join the Conversation #WolframTechConf

Abstract

In this talk we will explore how to deal with collections of pictures in the WL. With the last iterations of the language, we have made it easier to get the information you want without straining your memory. Now you can seamlessly integrate your pictures’ content and metadata into your workflow while leveraging our built-in capabilities for data analysis, statistics, geography, time series processing, and image classification.

Working with image collections

Quit[]

Short[files=FileNames["~/Desktop/Android/Backup/Pictures/Armenia/*.jpg"]]

n=Length[files]

Import[files[[1]],"ImageSize"]

bitsize=Quantity[Times@@N@%,"Bits"]

n bitsize

UnitConvert[%,"Gigabytes"]

(*Import/@files*)

Extracting the image metadata

exif=Import["~/Desktop/Android/Backup/Pictures/Armenia/*.jpg","Exif"];

Dataset[RandomChoice[exif]]

props=Sort@{"ExposureTime","ISOSpeedRatings","FocalLength","ShutterSpeedValue","ExposureIndex","DateTimeOriginal","ApertureValue"};

Dataset[RandomSample[exif,15]][All, props]

Photography metadata

ClearAll[pieChart]
pieChart[prop_, t_:0, showOther : _?BooleanQ : False] := 
Module[
	{data, tally, chart, selection, other},
	data = DeleteMissing[Lookup[exif,prop]];
	tally = AssociationThread @@ Transpose[Tally[SortBy[data, If[StringQ, ToExpression, Identity]]]];
	selection = Select[tally, # > t&];
	If[showOther,
		other = Association["other"->Total[Complement[tally, selection]]],
		other = Association[]
	];
	chart = PieChart[
		Join[selection, other],
		ChartLabels -> Placed[Automatic, "RadialOutside"],
		(*PerformanceGoal -> "Speed",*)
		PlotRange -> All,
		SectorOrigin -> 0];
	Labeled[chart, prop]
]

Manipulate[pieChart["ExposureTime",n],{n,0,20,2}]

props=Sort@{"ExposureTime","ISOSpeedRatings","FocalLength","ShutterSpeedValue","ExposureIndex"};

Multicolumn[pieChart[#,8]&/@props,3,Appearance->"Horizontal"]

http://www.wolfram.com/language/11/computational-photography/import-and-analyze-a-collection-from-social-media.html

Temporal metadata

DateHistogram[Lookup[exif,"DateTimeOriginal"],"Day"]

TimelinePlot[RandomSample[AssociationThread[imgs,Lookup[exif,"DateTimeOriginal"]],20]]

Geographical metadata

DeleteMissing[Lookup[exif,{"GPSLatitude","GPSLongitude","GPSAltitude"}],1,2]//Short

pos = Import["~/Desktop/Android/Backup/Pictures/Armenia/*.jpg","GeoPosition"];

Short[pos,3]

positions=DeleteCases[pos,None];

GeoGraphics[{AbsolutePointSize[5],Point/@positions}]

GeoGraphics[{Polygon[(Entity["Armenia", Entity["Country","Armenia"], "Entity[\"Country\", \"Armenia\"]", "country"])],
AbsolutePointSize[8],Red,Map[Tooltip[Point[#],Row[{Latitude[#],Longitude[#]}]]&,positions]},
 GeoRange->(Entity["Armenia", Entity["Country","Armenia"], "Entity[\"Country\", \"Armenia\"]", "country"])]

{height,location}=Transpose[DeleteCases[Transpose[{positions[[All,1,3]],positions}],{0.,_}]];

GeoGraphics[{Polygon[(Entity["Armenia", Entity["Country","Armenia"], "Entity[\"Country\", \"Armenia\"]", "country"])],AbsolutePointSize[6],MapThread[{ColorData["RustTones"][#1],Tooltip[Point[#2],Quantity[#3,"Meters"]]}&,{Rescale[height],location,height}]},
GeoRange->(Entity["Armenia", Entity["Country","Armenia"], "Entity[\"Country\", \"Armenia\"]", "country"])]

Geographical metadata

imgs =Import["~/Desktop/Android/Backup/Pictures/Armenia/*.jpg","Thumbnail",IncludeMetaInformation->None];

{positions, posimage}=Transpose[DeleteCases[Transpose[{pos,imgs}],{None,_}]];

GeoGraphics[{Polygon[(Entity["Armenia", Entity["Country","Armenia"], "Entity[\"Country\", \"Armenia\"]", "country"])],
Black,GeoPath[positions],
AbsolutePointSize[8],Red,MapThread[Tooltip[Point[#],Labeled[#2,Row[{Latitude[#],Longitude[#]}]]]&,{positions, posimage}]},
 GeoRange->(Entity["Armenia", Entity["Country","Armenia"], "Entity[\"Country\", \"Armenia\"]", "country"])]

GeoDistance[positions]

{dist,tour}=FindShortestTour[MapAt[Most,positions,{All,1}]];

GeoDistance[positions[[Most[tour]]]]

GeoGraphics[{Polygon[(Entity["Armenia", Entity["Country","Armenia"], "Entity[\"Country\", \"Armenia\"]", "country"])],
Black,GeoPath[positions[[Most[tour]]]],
AbsolutePointSize[8],Red,MapThread[Tooltip[Point[#],Labeled[#2,Row[{Latitude[#],Longitude[#]}]]]&,{positions, posimage}]},
 GeoRange->(Entity["Armenia", Entity["Country","Armenia"], "Entity[\"Country\", \"Armenia\"]", "country"])]

Looking into the data

monastery=;

Nearest[imgs][monastery,5]

Nearest[imgs,DistanceFunction->"NormalizedMutualInformationVariation"][monastery,5]

myNearest=Nearest[imgs,DistanceFunction->"NormalizedMutualInformationVariation"];
myNearest[monastery,5]

Looking into the data - semantics

featureExtractor=FeatureExtraction[imgs];
imageFeatures=featureExtractor[imgs];

featureExtractor

featureExtractor[monastery]//Short

With[{nfun = Nearest[imageFeatures -> imgs]},
 semanticNearest[img_Image, n_: 1] := nfun[featureExtractor[img], n]
]

semanticNearest[monastery,5]

semanticNearest[monastery,100]//ImageCollage

RandomSample[imgs,100]//ImageCollage

ClusteringTree[RandomSample[Thread[imageFeatures->Image[imgs,ImageSize->40]],20],
GraphLayout-> "SpringEmbedding",ImageSize->600]

clusters=FindClusters[imageFeatures,10,Method->"KMeans"];

rules=Dispatch[Thread[imageFeatures->Image[imgs,ImageSize->60]]];

RandomSample[#,UpTo[5]]&/@clusters/.rules//Grid

Looking into the data - compositions

list=Import[#,ImageSize->{600}]&/@{
"/Users/giulio/Desktop/Android/Backup/Pictures/Armenia/IMG_20160827_123615.jpg",
"/Users/giulio/Desktop/Android/Backup/Pictures/Armenia/IMG_20160827_123617.jpg",
"/Users/giulio/Desktop/Android/Backup/Pictures/Armenia/IMG_20160827_123621.jpg"
};

TabView[list]

aligned=ImageAlign[list];

mask=ImageMultiply[AlphaChannel/@aligned]

fixed=ImageMultiply[RemoveAlphaChannel[#],mask]&/@aligned

ImageExposureCombine

combination=ImageExposureCombine[%]

ImageSubtract[mask,Erosion[mask,50]]

Inpaint[combination,ColorNegate@mask,Method->{"TextureSynthesis",Masking->ImageSubtract[mask,Erosion[mask,50]]}]

Looking into the data - compositions

crop=ImagePad[#,-BorderDimensions[mask]-5]&/@fixed

ListLogPlot[FindCameraResponse[crop]]

hdri=CreateHDRImage[crop,Automatic,None]

Manipulate[ImageMultiply[hdri,2^a],{{a,0},-2,2}]

Manipulate[TabView[{
crop[[2]],
ImageExposureCombine[crop],
Dynamic@ColorToneMapping[hdri,a]
}
],{{a,.7},.5,1}]

Thank you!