You need to identify each object before finding angles. You only need the border of the objects, so you can also reduce your initial input. Then you just need to follow each individual border to find your angles, the centroid is located immediately after you know each individual border.
Using the code below, here is what you get (a centroid is a red dot, white text is rotation in degrees):

Please note that your input is not binary, so I used a very simple threshold for this. In addition, the following code is the easiest way to achieve this; there are faster methods in any decent library.
import sys import math from PIL import Image, ImageOps, ImageDraw orig = ImageOps.grayscale(Image.open(sys.argv[1])) orig_bin = orig.point(lambda x: 0 if x < 128 else 255) im = orig_bin.load() border = Image.new('1', orig.size, 'white') width, height = orig.size bim = border.load() # Keep only border points for x in xrange(width): for y in xrange(height): if im[x, y] == 255: continue if im[x+1, y] or im[x-1, y] or im[x, y+1] or im[x, y-1]: bim[x, y] = 0 else: bim[x, y] = 255 # Find each border (the trivial dummy way). def follow_border(im, x, y, used): work = [(x, y)] border = [] while work: x, y = work.pop() used.add((x, y)) border.append((x, y)) for dx, dy in ((1, 0), (-1, 0), (0, 1), (0, -1), (1, 1), (-1, -1), (1, -1), (-1, 1)): px, py = x + dx, y + dy if im[px, py] == 255 or (px, py) in used: continue work.append((px, py)) return border used = set() border = [] for x in xrange(width): for y in xrange(height): if bim[x, y] == 255 or (x, y) in used: continue b = follow_border(bim, x, y, used) border.append(b) # Find the corners and centroid of each rectangle. rectangle = [] for b in border: xmin, xmax, ymin, ymax = width, 0, height, 0 mean_x, mean_y = 0, 0 b = sorted(b) top_left, bottom_right = b[0], b[-1] for x, y in b: mean_x += x mean_y += y centroid = (mean_x / float(len(b)), mean_y / float(len(b))) b = sorted(b, key=lambda x: x[1]) curr = 0 while b[curr][1] == b[curr + 1][1]: curr += 1 top_right = b[curr] curr = len(b) - 1 while b[curr][1] == b[curr - 1][1]: curr -= 1 bottom_left = b[curr] rectangle.append([ [top_left, top_right, bottom_right, bottom_left], centroid]) result = orig.convert('RGB') draw = ImageDraw.Draw(result) for corner, centroid in rectangle: draw.line(corner + [corner[0]], fill='red', width=2) cx, cy = centroid draw.ellipse((cx - 2, cy - 2, cx + 2, cy + 2), fill='red') rotation = math.atan2(corner[0][1] - corner[1][1], corner[1][0] - corner[0][0]) rdeg = math.degrees(rotation) draw.text((cx + 10, cy), text='%.2f' % rdeg) result.save(sys.argv[2])