[FFmpeg-devel] [PATCH] lavfi: edgedetect filter
Clément Bœsch
ubitux at gmail.com
Tue Aug 7 20:44:25 CEST 2012
On Tue, Aug 07, 2012 at 08:02:47PM +0200, Nicolas George wrote:
> Le primidi 21 thermidor, an CCXX, Clément Bœsch a écrit :
> > FIXME: bump lavfi minor
> > ---
> > Canny Edge Detection, with no real tweak. Here are the results:
> > http://imgur.com/a/ujsG5
>
> I do not know the algorithm, I can not comment on that part. Looks good,
> though.
>
The algorithm is the kinda the more common. I added a @url
https://en.wikipedia.org/wiki/Canny_edge_detector on top of the file for
reference.
[...]
> > +static int config_props(AVFilterLink *inlink)
> > +{
> > + AVFilterContext *ctx = inlink->dst;
> > + EdgeDetectContext *edgedetect = ctx->priv;
> > +
> > + edgedetect->tmpbuf = av_malloc (inlink->w * inlink->h);
>
> > + edgedetect->gradients = av_mallocz(inlink->w * inlink->h * sizeof(*edgedetect->gradients));
>
> av_calloc(), to guard against overflows?
>
Changed locally.
> > + edgedetect->directions = av_malloc (inlink->w * inlink->h);
> > + if (!edgedetect->tmpbuf || !edgedetect->gradients || !edgedetect->directions)
> > + return AVERROR(ENOMEM);
> > + return 0;
> > +}
> > +
> > +static void gaussian_blur(AVFilterContext *ctx, int w, int h,
> > + uint8_t *dst, int dst_linesize,
> > + const uint8_t *src, int src_linesize)
> > +{
> > + int i, j;
> > +
> > + memcpy(dst, src, w);
> > + memcpy(dst + dst_linesize, src + src_linesize, w);
> > + for (j = 2; j < h - 2; j++) {
> > + dst[j*dst_linesize ] = src[j*src_linesize ];
> > + dst[j*dst_linesize+1] = src[j*src_linesize+1];
> > + for (i = 2; i < w - 2; i++) {
> > + dst[j*dst_linesize + i] =
> > + ((src[(j-2)*src_linesize + (i-2)] + src[(j+2)*src_linesize + (i-2)]) * 2
> > + + (src[(j-2)*src_linesize + (i-1)] + src[(j+2)*src_linesize + (i-1)]) * 4
> > + + (src[(j-2)*src_linesize + i ] + src[(j+2)*src_linesize + i ]) * 5
> > + + (src[(j-2)*src_linesize + (i+1)] + src[(j+2)*src_linesize + (i+1)]) * 4
> > + + (src[(j-2)*src_linesize + (i+2)] + src[(j+2)*src_linesize + (i+2)]) * 2
> > +
> > + + (src[(j-1)*src_linesize + (i-2)] + src[(j-1)*src_linesize + (i-2)]) * 4
> > + + (src[(j-1)*src_linesize + (i-1)] + src[(j-1)*src_linesize + (i-1)]) * 9
> > + + (src[(j-1)*src_linesize + i ] + src[(j-1)*src_linesize + i ]) * 12
> > + + (src[(j-1)*src_linesize + (i+1)] + src[(j-1)*src_linesize + (i+1)]) * 9
> > + + (src[(j-1)*src_linesize + (i+2)] + src[(j-1)*src_linesize + (i+2)]) * 4
> > +
> > + + src[j*src_linesize + (i-2)] * 5
> > + + src[j*src_linesize + (i-1)] * 12
> > + + src[j*src_linesize + i ] * 15
> > + + src[j*src_linesize + (i+1)] * 12
> > + + src[j*src_linesize + (i+2)] * 5) / 159;
> > + }
> > + dst[j*dst_linesize + i ] = src[j*src_linesize + i ];
> > + dst[j*dst_linesize + i+1] = src[j*src_linesize + i+1];
> > + }
> > + memcpy(dst + j *dst_linesize, src + j *src_linesize, w);
> > + memcpy(dst + (j+1)*dst_linesize, src + (j+1)*src_linesize, w);
>
> Is gcc smart enough to avoid all those multiplications by "linesize"? Just
> adding "src += linesize; dst += linesize;" would probably be more readable
> anyway.
>
I'll look at this deeper. I'm not sure doing increment all the time will
really improve things...
> > +}
> > +
> > +enum {
> > + DIRECTION_45UP,
> > + DIRECTION_45DOWN,
> > + DIRECTION_HORIZONTAL,
> > + DIRECTION_VERTICAL,
> > +};
> > +
> > +static int get_rounded_direction(int gx, int gy)
> > +{
> > + float tanpi8gx, tan3pi8gx;
> > +
> > + /* reference angles:
> > + * tan( pi/8) = sqrt(2)-1 ~= 0.41421...
> > + * tan(3pi/8) = sqrt(2)+1 ~= 2.41421...
> > + * Gy/Gx is the tangent of theta, so Gy/Gx is compared against <ref-angle>,
> > + * or more simply Gy against <ref-angle>*Gx
> > + */
> > + if (gx) {
> > + if (gx < 0) // left side, switch signs
> > + gx = -gx, gy = -gy;
> > + tanpi8gx = (M_SQRT2-1) * gx;
> > + tan3pi8gx = (M_SQRT2+1) * gx;
> > + if (gy > -tan3pi8gx && gy < -tanpi8gx) return DIRECTION_45UP;
> > + if (gy > -tanpi8gx && gy < tanpi8gx) return DIRECTION_HORIZONTAL;
> > + if (gy > tanpi8gx && gy < tan3pi8gx) return DIRECTION_45DOWN;
> > + }
> > + return DIRECTION_VERTICAL;
> > +}
>
> A pure integer version would be nicer and more FATE-friendly. Since gx and
> gy are bounded by ±256, the extra precision is not necessary:
>
mmh not really 256, more like [-1020;1020] afaict.
> if (gy << 16 > 158217) return ...
>
> (16 instead of 8 if someone wants to implement higher bit depths)
>
I'll give it a try as well.
[...]
Thanks for the review!
--
Clément B.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120807/01c34749/attachment.asc>
More information about the ffmpeg-devel
mailing list