Anything obvious in optimization missed in my left join query?
SELECT  o.id
    FROM  objects AS o
    JOIN  uchog7x7  ON o.id = u.id  -- Not LEFT
    WHERE  u.needs_update = 1
      -- AND  u.id IS NOT NULL   -- not needed
      AND  o.object_name = 'face'


Don't use CHAR() unless the value is a constant length.

What fraction of the rows have 'face'?  What percentage have needs_update?

The optimizer, when given no good choice, starts with the smaller table.  According to EXPLAIN, it found about 1 row with "needs_update".  Probably that is far off, and you need to remove that index.

What version of MySQL are you using?  5.7 has improved the 'cost models', and might do a better job.

Other notes:

Don't use tinyblob; use VARBINARY(255) instead.

Why are *coord and image_data_size going into blobs; they sound like numeric values?

What will you do with the ids that come back from the query?  Some heavy-duty image processing?  If so, consider adding LIMIT 1 (or LIMIT 10) so that the query comes back faster.  I assume you will pick up others later.