In [120]:
using DataFrames
using Gadfly
using Images
using ImageMagick

In [1]:
path = "/home/fliang/tmp/facial-keypoints"


Out[1]:
"/home/fliang/tmp/facial-keypoints"

In [12]:
train_data = readtable("$(path)/training.csv")
test_data = readtable("$(path)/test.csv")
describe(train_data)


left_eye_center_x
Min      22.7633446452
1st Qu.  65.08289546
Median   66.4975659574
Mean     66.35902124475366
3rd Qu.  68.0247516599
Max      94.68928
NAs      10
NA%      0.14%

left_eye_center_y
Min      1.616512
1st Qu.  35.90045101045
Median   37.5280551724
Mean     37.65123419193396
3rd Qu.  39.2584493713
Max      80.5026490272
NAs      10
NA%      0.14%

right_eye_center_x
Min      0.686592
1st Qu.  28.783338947375
Median   30.2513779589
Mean     30.30610151407975
3rd Qu.  31.7683336949
Max      85.0393813333
NAs      13
NA%      0.18%

right_eye_center_y
Min      4.091264
1st Qu.  36.3276806153
Median   37.81327345455
Mean     37.97694257172697
3rd Qu.  39.566729074449995
Max      81.2709105058
NAs      13
NA%      0.18%

left_eye_inner_corner_x
Min      19.0649535927
1st Qu.  58.03933907665
Median   59.3046153846
Mean     59.15933943740387
3rd Qu.  60.51981039745
Max      84.4409912283
NAs      4778
NA%      67.78%

left_eye_inner_corner_y
Min      27.1900981132
1st Qu.  36.626283495150005
Median   37.8780397351
Mean     37.94475232796773
3rd Qu.  39.2603476873
Max      66.5625592938
NAs      4778
NA%      67.78%

left_eye_outer_corner_x
Min      27.571878986
1st Qu.  71.7165027954
Median   73.2478238631
Mean     73.3304779831461
3rd Qu.  75.0156445444
Max      95.2580903776
NAs      4782
NA%      67.84%

left_eye_outer_corner_y
Min      26.2500226415
1st Qu.  36.0855226976
Median   37.6390153846
Mean     37.70700831079299
3rd Qu.  39.37348879895
Max      64.618230116
NAs      4782
NA%      67.84%

right_eye_inner_corner_x
Min      5.75104621744
1st Qu.  35.50612576405
Median   36.65156194525
Mean     36.652606948057254
3rd Qu.  37.753570847975
Max      70.7149659863
NAs      4781
NA%      67.83%

right_eye_inner_corner_y
Min      26.2500226415
1st Qu.  36.7667825825
Median   37.9440749321
Mean     37.98990191451049
3rd Qu.  39.192916548925
Max      69.8088030886
NAs      4781
NA%      67.83%

right_eye_outer_corner_x
Min      3.98011698358
1st Qu.  20.585808411625
Median   22.53595408165
Mean     22.384504479169358
3rd Qu.  24.2377005302
Max      61.428580499
NAs      4781
NA%      67.83%

right_eye_outer_corner_y
Min      25.1238282899
1st Qu.  36.534381649574996
Median   37.867071197550004
Mean     38.03349517525053
3rd Qu.  39.415051034475
Max      70.7467966905
NAs      4781
NA%      67.83%

left_eyebrow_inner_end_x
Min      17.8887172181
1st Qu.  54.515586985249996
Median   56.2449747899
Mean     56.06851307930929
3rd Qu.  57.946415408675
Max      79.7878306003
NAs      4779
NA%      67.8%

left_eyebrow_inner_end_y
Min      15.859360558
1st Qu.  27.6172443833
Median   29.5288719956
Mean     29.332678249311716
3rd Qu.  31.158830344175
Max      60.8758963044
NAs      4779
NA%      67.8%

left_eyebrow_outer_end_x
Min      32.2064315043
1st Qu.  77.6739164832
Median   79.7842285714
Mean     79.4828258641995
3rd Qu.  81.59072
Max      94.2699574468
NAs      4824
NA%      68.44%

left_eyebrow_outer_end_y
Min      10.5223245283
1st Qu.  27.6679480519
Median   29.7738129496
Mean     29.734860732432317
3rd Qu.  31.8356210526
Max      60.5002978487
NAs      4824
NA%      68.44%

right_eyebrow_inner_end_x
Min      6.92101430767
1st Qu.  37.55228589605
Median   39.29884828355
Mean     39.32213692201748
3rd Qu.  40.917159839325
Max      76.5823884233
NAs      4779
NA%      67.8%

right_eyebrow_inner_end_y
Min      16.476
1st Qu.  27.790606976475
Median   29.56934679485
Mean     29.502998474112996
3rd Qu.  31.251663780575
Max      62.0831770544
NAs      4779
NA%      67.8%

right_eyebrow_outer_end_x
Min      3.82624305628
1st Qu.  13.562183125475
Median   15.785708698
Mean     15.871177472719149
3rd Qu.  17.99904048585
Max      58.4182160877
NAs      4813
NA%      68.28%

right_eyebrow_outer_end_y
Min      13.2244528302
1st Qu.  28.206046153875
Median   30.3201602048
Mean     30.42816591187344
3rd Qu.  32.654767647925
Max      66.7513292886
NAs      4813
NA%      68.28%

nose_tip_x
Min      12.9446992813
1st Qu.  46.6023703704
Median   48.424713253
Mean     48.37418629032876
3rd Qu.  50.3304369231
Max      89.438592
NAs      0
NA%      0.0%

nose_tip_y
Min      17.932414359
1st Qu.  59.2926967742
Median   63.4514206897
Mean     62.71588359736172
3rd Qu.  66.4926857143
Max      95.9356444444
NAs      0
NA%      0.0%

mouth_left_corner_x
Min      22.9233619709
1st Qu.  61.2571428571
Median   63.1782857143
Mean     63.2857351209867
3rd Qu.  65.3762428049
Max      84.7671231511
NAs      4780
NA%      67.81%

mouth_left_corner_y
Min      57.0232580609
1st Qu.  72.8757073171
Median   75.7786890756
Mean     75.97071433583544
3rd Qu.  78.8791232877
Max      94.673637358
NAs      4780
NA%      67.81%

mouth_right_corner_x
Min      2.2457663423
1st Qu.  30.7976459348
Median   32.98230472525
Mean     32.90040370265762
3rd Qu.  35.10130170425
Max      74.017993112
NAs      4779
NA%      67.8%

mouth_right_corner_y
Min      56.6902081856
1st Qu.  73.256471951625
Median   76.0005923775
Mean     76.17976785460498
3rd Qu.  78.95635739024999
Max      95.5106784444
NAs      4779
NA%      67.8%

mouth_center_top_lip_x
Min      12.605173056
1st Qu.  46.49457099425
Median   47.9054900422
Mean     47.97541157202031
3rd Qu.  49.2964878752
Max      83.9890815477
NAs      4774
NA%      67.73%

mouth_center_top_lip_y
Min      56.719042631
1st Qu.  69.396747557
Median   72.6051731449
Mean     72.91944259683736
3rd Qu.  76.22164436475
Max      94.5483586149
NAs      4774
NA%      67.73%

mouth_center_bottom_lip_x
Min      12.536476725
1st Qu.  46.573702758625
Median   48.59497754255
Mean     48.56947217227819
3rd Qu.  50.6776308333
Max      89.438592
NAs      33
NA%      0.47%

mouth_center_bottom_lip_y
Min      25.8505025641
1st Qu.  75.54971531525
Median   78.69632621535
Mean     78.9701462450369
3rd Qu.  82.233992968225
Max      95.8089831215
NAs      33
NA%      0.47%

Image
Length  7049
Type    UTF8String
NAs     0
NA%     0.0%
Unique  6494

Converts Image column from strings into Images


In [114]:
function stringToImage(image_string)
    return grayim(convert(Array{UInt8}, reshape(readdlm(IOBuffer(image_string)), 96, 96)))
end
train_data[:Image] = map(stringToImage, train_data[:Image])
test_data[:Image] = map(stringToImage, test_data[:Image])


Out[114]:
1783-element DataArrays.DataArray{Any,1}:
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 ⋮                                                                                                                                         
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y
 Gray Images.Image with:
  data: 96x96 Array{FixedPointNumbers.UFixed{UInt8,8},2}
  properties:
    colorspace: Gray
    spatialorder:  x y

Visualize some of the data


In [140]:
example_id = 1
train_data[:Image][example_id]


Out[140]:

In [198]:
train_idx = 1
xs = convert(Array{Float64}, train_data[train_idx,[:left_eye_center_x, :right_eye_center_x, :nose_tip_x, :mouth_center_top_lip_x]])
ys = -1*convert(Array{Float64}, train_data[train_idx,[:left_eye_center_y, :right_eye_center_y, :nose_tip_y, :mouth_center_top_lip_y]])
plot(x=xs,y=ys, Coord.Cartesian(xmin=0, xmax=96, ymin=-96, ymax=0))


Out[198]:
x -150 -100 -50 0 50 100 150 200 250 -100 -95 -90 -85 -80 -75 -70 -65 -60 -55 -50 -45 -40 -35 -30 -25 -20 -15 -10 -5 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 105 110 115 120 125 130 135 140 145 150 155 160 165 170 175 180 185 190 195 -100 0 100 200 -100 -90 -80 -70 -60 -50 -40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 -250 -200 -150 -100 -50 0 50 100 150 -195 -190 -185 -180 -175 -170 -165 -160 -155 -150 -145 -140 -135 -130 -125 -120 -115 -110 -105 -100 -95 -90 -85 -80 -75 -70 -65 -60 -55 -50 -45 -40 -35 -30 -25 -20 -15 -10 -5 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 -200 -100 0 100 -200 -190 -180 -170 -160 -150 -140 -130 -120 -110 -100 -90 -80 -70 -60 -50 -40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 100 y

Simple benchmark using column means


In [265]:
colMeans = map(x -> x[1], colwise(x -> mean(dropna(x)), train_data[names(train_data) .!= :Image]))


Out[265]:
30-element Array{Any,1}:
 66.359 
 37.6512
 30.3061
 37.9769
 59.1593
 37.9448
 73.3305
 37.707 
 36.6526
 37.9899
 22.3845
 38.0335
 56.0685
  ⋮     
 15.8712
 30.4282
 48.3742
 62.7159
 63.2857
 75.9707
 32.9004
 76.1798
 47.9754
 72.9194
 48.5695
 78.9701

In [313]:
predictions = DataFrame()
predictions[:ImageId] = 1:size(test_data,1)
mat = repmat(colMeans', size(test_data,1), 1)
predictions = hcat(predictions, DataFrame([mat[:,i] for i in 1:size(mat,2)], names(train_data)[names(train_data) .!= :Image]))

head(predictions)


Out[313]:
ImageIdleft_eye_center_xleft_eye_center_yright_eye_center_xright_eye_center_yleft_eye_inner_corner_xleft_eye_inner_corner_yleft_eye_outer_corner_xleft_eye_outer_corner_yright_eye_inner_corner_xright_eye_inner_corner_yright_eye_outer_corner_xright_eye_outer_corner_yleft_eyebrow_inner_end_xleft_eyebrow_inner_end_yleft_eyebrow_outer_end_xleft_eyebrow_outer_end_yright_eyebrow_inner_end_xright_eyebrow_inner_end_yright_eyebrow_outer_end_xright_eyebrow_outer_end_ynose_tip_xnose_tip_ymouth_left_corner_xmouth_left_corner_ymouth_right_corner_xmouth_right_corner_ymouth_center_top_lip_xmouth_center_top_lip_ymouth_center_bottom_lip_xmouth_center_bottom_lip_y
1166.3590212447536637.6512341919339630.3061015140797537.9769425717269759.1593394374038737.9447523279677373.330477983146137.7070083107929936.65260694805725437.9899019145104922.38450447916935838.0334951752505356.0685130793092929.33267824931171679.482825864199529.73486073243231739.3221369220174829.50299847411299615.87117747271914930.4281659118734448.3741862903287662.7158835973617263.285735120986775.9707143358354432.9004037026576276.1797678546049847.9754115720203172.9194425968373648.5694721722781978.9701462450369
2266.3590212447536637.6512341919339630.3061015140797537.9769425717269759.1593394374038737.9447523279677373.330477983146137.7070083107929936.65260694805725437.9899019145104922.38450447916935838.0334951752505356.0685130793092929.33267824931171679.482825864199529.73486073243231739.3221369220174829.50299847411299615.87117747271914930.4281659118734448.3741862903287662.7158835973617263.285735120986775.9707143358354432.9004037026576276.1797678546049847.9754115720203172.9194425968373648.5694721722781978.9701462450369
3366.3590212447536637.6512341919339630.3061015140797537.9769425717269759.1593394374038737.9447523279677373.330477983146137.7070083107929936.65260694805725437.9899019145104922.38450447916935838.0334951752505356.0685130793092929.33267824931171679.482825864199529.73486073243231739.3221369220174829.50299847411299615.87117747271914930.4281659118734448.3741862903287662.7158835973617263.285735120986775.9707143358354432.9004037026576276.1797678546049847.9754115720203172.9194425968373648.5694721722781978.9701462450369
4466.3590212447536637.6512341919339630.3061015140797537.9769425717269759.1593394374038737.9447523279677373.330477983146137.7070083107929936.65260694805725437.9899019145104922.38450447916935838.0334951752505356.0685130793092929.33267824931171679.482825864199529.73486073243231739.3221369220174829.50299847411299615.87117747271914930.4281659118734448.3741862903287662.7158835973617263.285735120986775.9707143358354432.9004037026576276.1797678546049847.9754115720203172.9194425968373648.5694721722781978.9701462450369
5566.3590212447536637.6512341919339630.3061015140797537.9769425717269759.1593394374038737.9447523279677373.330477983146137.7070083107929936.65260694805725437.9899019145104922.38450447916935838.0334951752505356.0685130793092929.33267824931171679.482825864199529.73486073243231739.3221369220174829.50299847411299615.87117747271914930.4281659118734448.3741862903287662.7158835973617263.285735120986775.9707143358354432.9004037026576276.1797678546049847.9754115720203172.9194425968373648.5694721722781978.9701462450369
6666.3590212447536637.6512341919339630.3061015140797537.9769425717269759.1593394374038737.9447523279677373.330477983146137.7070083107929936.65260694805725437.9899019145104922.38450447916935838.0334951752505356.0685130793092929.33267824931171679.482825864199529.73486073243231739.3221369220174829.50299847411299615.87117747271914930.4281659118734448.3741862903287662.7158835973617263.285735120986775.9707143358354432.9004037026576276.1797678546049847.9754115720203172.9194425968373648.5694721722781978.9701462450369

In [331]:
submission = stack(predictions, names(predictions[names(predictions) .!= :ImageId]))
submission = hcat(DataFrame(RowId=1:size(submission, 1)), submission)
rename!(submission, :variable, :FeatureName)
rename!(submission, :value, :Location)
example = readtable("$(path)/SampleSubmission.csv")
delete!(example, :Location)
submission = join(example, submission, on=:RowId)
submission = submission[:,[:RowId, :Location]]

writetable("$(path)/output.csv", submission)

Build classifier trained on image patches

The idea is to extract an image patch centered at each keypoint and train a classifier on these. Then, for a test image we run a sliding window across the image and predict the keypoint to be where the activation of the sliding window is maximized.


In [ ]: