non-free packages are packages not complying to the Debian Free Software Guidelines definition. E.g.:
nvidia-driver which provides a proprietary driver.
contrib packages are packages that do comply with the DFSG, but depend on non-free packages, or which depend on some non-free software downloaded (by the package or having to be downloaded manually) to work properly. So they don't end up in
bumblebee-nvidia which while DFSG compliant, isn't really useful without the non-free package
nvidia-driver, so it's put in the
contrib section, or
vice which requires to download (while respecting copyrights and laws) ROMs to work properly.
If somebody doesn't want to or can't use non-free software, that person most probably doesn't need or won't be able to use software depending on it, so it's more useful to put them separately in a contrib section. That person won't even have to download the contrib section.
UPDATE: the software in contrib, and its sources are still available for free use. Interesting parts could be reused in an other project, or the non-free (or non available) parts it depends upon could be replaced (e.g.: replace graphics, music etc. assets for a game engine in contrib). Having it separate from non-free helps to know which parts can be reused.
trivia: the Open Source Definition was initially created by removing any mention of Debian in DFSG.