I try to avoid image CAPTCHA these days. I've found that a combination of techniques has totally eliminated spam without requiring the user to do anything.
Generate a unique, random key via PHP and add it to the session. This is then added to the form as a hidden field. If the keys don't match when the form is sent, the submission is rejected.
Place a text field with a nice attractive name such as 'message' and use CSS to hide it from human users. Since bots tend to fill in every form element, if this field is submitted with a value, the submission is discarded.
Add a hidden field containing the timestamp at which the form was generated. Use this to check a minimum time has elapsed before the submission is accepted. Obviously this is dependent on the nature of your form, but for something like an email form if it is submitted in under 5-10 seconds chances are it wasn't done by a human.
You can also check the $_SERVER['HTTP_REFERRER'] property to ensure the submission came directly from your page, although I would tend to only reject if the referrer was present and different, and even then this is easily spoofed so it's only a little extra check.
You should also perform general input filtering and validation. Compare the submitted fields against a whitelist. Where extra fields sent? If so the submission likely didn't come from your form. Make sure the data matches the format you expect, and be as strict as possible. If you don't allow HTML links, check for them in the submission. If you are expecting numerical data, make sure that's what you get etc.
At the moment I work on a site that gets a good few million hits a month and our online mail forms use these techniques. To date, we haven't had a single spam message get through, though obviously your mileage may vary.