Start by finding all groups of objects, where a group of objects is a collection of objects which overlap. Standard collision detection should do the job. Assign to each group a unique colour. Any colour would do.
Render all your objects as solid colours, using the group colour, to a texture.
Create a new outline texture with the same dimensions as the render target. Scan through each texel of the render target and determine if it's a different colour to any surrounding texels. If it is, change the corresponding texel in the outline texture to the line colour you want.
Finally, take this outline texture and render it over the top of the image you want to draw on the screen (you could of course do this at the same time as the edge detection in a fragment shader and avoid creating the edge texture in the first place).
If you perform this step on the cpu by using a for loop to go through the render target's texels, then this will be pretty slow, but probably good enough to test and even use in some cases. To use this in real time you would be best to handle this in a shader.
A fragment shader to do this edge detection might look like this;
precision mediump float;
uniform sampler2D s_texture;
varying vec2 v_texCoord;
void main()
{
gl_FragColor = vec4(0.0);
vec4 baseColor = texture2D(s_texture, v_texCoord);
gl_FragColor += baseColor - texture2D(s_texture, top);
gl_FragColor += baseColor - texture2D(s_texture, topRight);
gl_FragColor += baseColor - texture2D(s_texture, right);
gl_FragColor += baseColor - texture2D(s_texture, bottomRight);
gl_FragColor += baseColor - texture2D(s_texture, bottom);
gl_FragColor += baseColor - texture2D(s_texture, bottomLeft);
gl_FragColor += baseColor - texture2D(s_texture, left);
gl_FragColor += baseColor - texture2D(s_texture, topLeft);
}
Where the second value in the texture2D look up is a 2d coordinate relative to v_texCoord. You would apply this by rendering the first render target as the texture on a full screen quad. This is similar to how you would apply full screen blurring effects such as a guassian blur.
The reason to use the first render target with solid colours is simply to make sure that there is no perceived edge between different objects that overlap. If you simply performed edge detection on the screen image you would probably find that it detects edges at the overlaps as well (assuming the objects have different colours/textures/lighting).