From patchwork Mon Jul 11 08:53:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thilo Borgmann X-Patchwork-Id: 36732 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:6da0:b0:8b:e47:9dbf with SMTP id wl32csp1229668pzb; Mon, 11 Jul 2022 01:53:34 -0700 (PDT) X-Google-Smtp-Source: AGRyM1sPleRvejS6B2Ajij/b0TgqneYTz0PSd1V/B/kGIUDpn/PVxGPmcpajNPvdXYd2I1tRVMVo X-Received: by 2002:aa7:dcc2:0:b0:43a:b180:bb12 with SMTP id w2-20020aa7dcc2000000b0043ab180bb12mr19870847edu.119.1657529614529; Mon, 11 Jul 2022 01:53:34 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1657529614; cv=none; d=google.com; s=arc-20160816; b=T49uJHpmUOyDJgW62UkHc/vqSw0m+k2NWO8vEQpESYqvzy14yuAkhnC468dYQhYVvM u86lH62HJLDapE/hLXakLwf6sDCvLchwZNADBA6RpLwQDx2eROb8MC2eZOlmBcjtoOb9 YxTK0qcQCtt4JQ5MB2EpVG2Nlm5yBKwZde0vuiBTk888IwXeccgAhc2/3dpMqT0hF7gW omVJoYmjOHhCNk3jCeAbP8mSE0kdNaIfyvaSsHvU+QTskkN6V/B7lnH8fezopYfmPsFG mTFAQd0ZD0df/HNLwhRorpXjEBQLEny+RSTelm9Jkauox/3dBEY80yicnXFE0HH+NMi4 OwNg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject:from:to :content-language:mime-version:date:message-id:dkim-signature :delivered-to; bh=3eElNc3yYOLvl5CpW8XWGCNrMEJZldi4lhT5iiUcisY=; b=iu+E27oBYrIby7HkGD3Nh1Nzq5qYSLHOuJNDz+JbAGvyDZHy2/zAok9DlUubvFkx66 8IYbnylhqmKRj5fczTHKLVxEoyzr7ZPD+HXln5aU0tq+kO5v2+paZgdm5HTzwfImAmYL KLLI+8Ykj2GakBY25dbEqjqIHc6d6dEX7lTw7U5O7aunpjcktykqosbIYCn0iCif9iRL ZwPL4Zm86NGDVTUYocxz0BdMfQUY/n2s099rQ6rnNGsYNW49xq9eXUKoLYJGn/nlYZ+A jQ0qkWF+JfwM7Dq67AF4oFm1RYD5I73afh4NUF7H7XMnhpO5lUU4mmuLpMMYymOywJjK CLDA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@mail.de header.s=mailde202009 header.b=wkRkTU2M; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mail.de Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id z8-20020aa7c648000000b004378ef44891si8499276edr.230.2022.07.11.01.53.32; Mon, 11 Jul 2022 01:53:34 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@mail.de header.s=mailde202009 header.b=wkRkTU2M; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=mail.de Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DCF5B68B4F0; Mon, 11 Jul 2022 11:53:28 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from shout02.mail.de (shout02.mail.de [62.201.172.25]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9D32168B668 for ; Mon, 11 Jul 2022 11:53:22 +0300 (EEST) Received: from postfix02.mail.de (postfix02.bt.mail.de [10.0.121.126]) by shout02.mail.de (Postfix) with ESMTP id 1ACA5A0CDD for ; Mon, 11 Jul 2022 10:53:22 +0200 (CEST) Received: from smtp04.mail.de (smtp04.bt.mail.de [10.0.121.214]) by postfix02.mail.de (Postfix) with ESMTP id 00F18A03C1 for ; Mon, 11 Jul 2022 10:53:21 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mail.de; s=mailde202009; t=1657529602; bh=5yZbcaDODig5USLwXsa7gcVZ2qFvx+u6aC+KbHeKB5g=; h=Message-ID:Date:To:From:Subject:From:To:CC:Subject:Reply-To; b=wkRkTU2MzfDnFE/QUH1avSD98keEM2LWikKLWPk3JUnk6ehBwLzNXhkgfMTC+ao8Q cAYN0YBrUjsJXE7CFqUH4ZMP4hV7DqqP6v1f61C0q74Jh9jSBQNFdHlnoYXS1brUY6 32JZ6osYtVFeC7S8Ts6SI61JX8T43kNCXDcveaNXLvb+iV/+B4ISxcYZPRxk52Jew8 9MxOmhmEgD7CAa98tIUAeQXBJ0xIYBPhaOqKNENzyj9oya5GotM3M98ZrET0aG3XZA 6F6opmA/cqQ5+Nzirg5GsSt2EKG2GHiKBZy6YeAHNElKEs7Q81KiOerbxtrvgHVLhh Pn1ruX06uv3YQ== Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtp04.mail.de (Postfix) with ESMTPSA id C39DAC00B9 for ; Mon, 11 Jul 2022 10:53:21 +0200 (CEST) Message-ID: <9bb7f1eb-b927-f2bc-7b4a-292f46ef1a9e@mail.de> Date: Mon, 11 Jul 2022 10:53:20 +0200 MIME-Version: 1.0 Content-Language: en-US To: FFmpeg development discussions and patches From: Thilo Borgmann X-purgate: clean X-purgate: This mail is considered clean (visit http://www.eleven.de for further information) X-purgate-type: clean X-purgate-Ad: Categorized by eleven eXpurgate (R) http://www.eleven.de X-purgate: This mail is considered clean (visit http://www.eleven.de for further information) X-purgate: clean X-purgate-size: 18524 X-purgate-ID: 154282::1657529601-000016C9-0927B88A/0/0 Subject: [FFmpeg-devel] [PATCH v2 1/2] lavfi/edge_common: Add 16bit versions of gaussian_blur and sobel X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: kJV8VaPCEjqN Hi, 1/2 adds 16 bit versions of ff_gaussian_blur and ff_sobel. 2/2 adds new mode to cropdetect. Thanks, Thilo From fc8c179e2de4dee3d32d2e02684f3e3215af63c6 Mon Sep 17 00:00:00 2001 From: Thilo Borgmann Date: Sun, 10 Jul 2022 12:40:27 +0200 Subject: [PATCH v2 1/2] lavfi/edge_common: Add 16bit versions of gaussian_blur and sobel --- libavfilter/edge_common.c | 134 ++++++++++++++++++++++++++++-------- libavfilter/edge_common.h | 14 +++- libavfilter/vf_blurdetect.c | 4 +- libavfilter/vf_edgedetect.c | 4 +- 4 files changed, 121 insertions(+), 35 deletions(-) diff --git a/libavfilter/edge_common.c b/libavfilter/edge_common.c index d72e8521cd..f0bf273b84 100644 --- a/libavfilter/edge_common.c +++ b/libavfilter/edge_common.c @@ -50,7 +50,7 @@ static int get_rounded_direction(int gx, int gy) void ff_sobel(int w, int h, uint16_t *dst, int dst_linesize, int8_t *dir, int dir_linesize, - const uint8_t *src, int src_linesize) + const uint8_t *src, int src_linesize, int src_stride) { int i, j; @@ -60,13 +60,43 @@ void ff_sobel(int w, int h, src += src_linesize; for (i = 1; i < w - 1; i++) { const int gx = - -1*src[-src_linesize + i-1] + 1*src[-src_linesize + i+1] - -2*src[ i-1] + 2*src[ i+1] - -1*src[ src_linesize + i-1] + 1*src[ src_linesize + i+1]; + -1*src[-src_linesize + (i-1)*src_stride] + 1*src[-src_linesize + (i+1)*src_stride] + -2*src[ (i-1)*src_stride] + 2*src[ (i+1)*src_stride] + -1*src[ src_linesize + (i-1)*src_stride] + 1*src[ src_linesize + (i+1)*src_stride]; const int gy = - -1*src[-src_linesize + i-1] + 1*src[ src_linesize + i-1] - -2*src[-src_linesize + i ] + 2*src[ src_linesize + i ] - -1*src[-src_linesize + i+1] + 1*src[ src_linesize + i+1]; + -1*src[-src_linesize + (i-1)*src_stride] + 1*src[ src_linesize + (i-1)*src_stride] + -2*src[-src_linesize + (i )*src_stride] + 2*src[ src_linesize + (i )*src_stride] + -1*src[-src_linesize + (i+1)*src_stride] + 1*src[ src_linesize + (i+1)*src_stride]; + + dst[i] = FFABS(gx) + FFABS(gy); + dir[i] = get_rounded_direction(gx, gy); + } + } +} + +void ff_sobel16(int w, int h, + uint16_t *dst, int dst_linesize, + int8_t *dir, int dir_linesize, + const uint8_t *src, int src_linesize, int src_stride) +{ + int i, j; + uint16_t *src16 = (uint16_t *)src; + int src16_stride = src_stride / 2; + int src16_linesize = src_linesize / 2; + + for (j = 1; j < h - 1; j++) { + dst += dst_linesize; + dir += dir_linesize; + src16 += src16_linesize; + for (i = 1; i < w - 1; i++) { + const int gx = + -1*src16[-src16_linesize + (i-1)*src16_stride] + 1*src16[-src16_linesize + (i+1)*src16_stride] + -2*src16[ (i-1)*src16_stride] + 2*src16[ (i+1)*src16_stride] + -1*src16[ src16_linesize + (i-1)*src16_stride] + 1*src16[ src16_linesize + (i+1)*src16_stride]; + const int gy = + -1*src16[-src16_linesize + (i-1)*src16_stride] + 1*src16[ src16_linesize + (i-1)*src16_stride] + -2*src16[-src16_linesize + (i )*src16_stride] + 2*src16[ src16_linesize + (i )*src16_stride] + -1*src16[-src16_linesize + (i+1)*src16_stride] + 1*src16[ src16_linesize + (i+1)*src16_stride]; dst[i] = FFABS(gx) + FFABS(gy); dir[i] = get_rounded_direction(gx, gy); @@ -141,37 +171,37 @@ void ff_double_threshold(int low, int high, int w, int h, // Applies gaussian blur, using 5x5 kernels, sigma = 1.4 void ff_gaussian_blur(int w, int h, uint8_t *dst, int dst_linesize, - const uint8_t *src, int src_linesize) + const uint8_t *src, int src_linesize, int src_stride) { int i, j; memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; for (j = 2; j < h - 2; j++) { - dst[0] = src[0]; - dst[1] = src[1]; + dst[0] = src[(0)*src_stride]; + dst[1] = src[(1)*src_stride]; for (i = 2; i < w - 2; i++) { /* Gaussian mask of size 5x5 with sigma = 1.4 */ - dst[i] = ((src[-2*src_linesize + i-2] + src[2*src_linesize + i-2]) * 2 - + (src[-2*src_linesize + i-1] + src[2*src_linesize + i-1]) * 4 - + (src[-2*src_linesize + i ] + src[2*src_linesize + i ]) * 5 - + (src[-2*src_linesize + i+1] + src[2*src_linesize + i+1]) * 4 - + (src[-2*src_linesize + i+2] + src[2*src_linesize + i+2]) * 2 - - + (src[ -src_linesize + i-2] + src[ src_linesize + i-2]) * 4 - + (src[ -src_linesize + i-1] + src[ src_linesize + i-1]) * 9 - + (src[ -src_linesize + i ] + src[ src_linesize + i ]) * 12 - + (src[ -src_linesize + i+1] + src[ src_linesize + i+1]) * 9 - + (src[ -src_linesize + i+2] + src[ src_linesize + i+2]) * 4 - - + src[i-2] * 5 - + src[i-1] * 12 - + src[i ] * 15 - + src[i+1] * 12 - + src[i+2] * 5) / 159; + dst[i] = ((src[-2*src_linesize + (i-2)*src_stride] + src[2*src_linesize + (i-2)*src_stride]) * 2 + + (src[-2*src_linesize + (i-1)*src_stride] + src[2*src_linesize + (i-1)*src_stride]) * 4 + + (src[-2*src_linesize + (i )*src_stride] + src[2*src_linesize + (i )*src_stride]) * 5 + + (src[-2*src_linesize + (i+1)*src_stride] + src[2*src_linesize + (i+1)*src_stride]) * 4 + + (src[-2*src_linesize + (i+2)*src_stride] + src[2*src_linesize + (i+2)*src_stride]) * 2 + + + (src[ -src_linesize + (i-2)*src_stride] + src[ src_linesize + (i-2)*src_stride]) * 4 + + (src[ -src_linesize + (i-1)*src_stride] + src[ src_linesize + (i-1)*src_stride]) * 9 + + (src[ -src_linesize + (i )*src_stride] + src[ src_linesize + (i )*src_stride]) * 12 + + (src[ -src_linesize + (i+1)*src_stride] + src[ src_linesize + (i+1)*src_stride]) * 9 + + (src[ -src_linesize + (i+2)*src_stride] + src[ src_linesize + (i+2)*src_stride]) * 4 + + + src[(i-2)*src_stride] * 5 + + src[(i-1)*src_stride] * 12 + + src[(i )*src_stride] * 15 + + src[(i+1)*src_stride] * 12 + + src[(i+2)*src_stride] * 5) / 159; } - dst[i ] = src[i ]; - dst[i + 1] = src[i + 1]; + dst[i ] = src[(i )*src_stride]; + dst[i + 1] = src[(i + 1)*src_stride]; dst += dst_linesize; src += src_linesize; @@ -179,3 +209,49 @@ void ff_gaussian_blur(int w, int h, memcpy(dst, src, w); dst += dst_linesize; src += src_linesize; memcpy(dst, src, w); } + +void ff_gaussian_blur16(int w, int h, + uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, int src_stride) +{ + int i, j; + uint16_t *src16 = (uint16_t *)src; + uint16_t *dst16 = (uint16_t *)dst; + int src16_stride = src_stride / 2; + int src16_linesize = src_linesize / 2; + int dst16_linesize = dst_linesize / 2; + + memcpy(dst16, src16, w*2); dst16 += dst16_linesize; src16 += src16_linesize; + memcpy(dst16, src16, w*2); dst16 += dst16_linesize; src16 += src16_linesize; + for (j = 2; j < h - 2; j++) { + dst16[0] = src16[(0)*src16_stride]; + dst16[1] = src16[(1)*src16_stride]; + for (i = 2; i < w - 2; i++) { + /* Gaussian mask of size 5x5 with sigma = 1.4 */ + dst16[i] = ((src16[-2*src16_linesize + (i-2)*src16_stride] + src16[2*src16_linesize + (i-2)*src16_stride]) * 2 + + (src16[-2*src16_linesize + (i-1)*src16_stride] + src16[2*src16_linesize + (i-1)*src16_stride]) * 4 + + (src16[-2*src16_linesize + (i )*src16_stride] + src16[2*src16_linesize + (i )*src16_stride]) * 5 + + (src16[-2*src16_linesize + (i+1)*src16_stride] + src16[2*src16_linesize + (i+1)*src16_stride]) * 4 + + (src16[-2*src16_linesize + (i+2)*src16_stride] + src16[2*src16_linesize + (i+2)*src16_stride]) * 2 + + + (src16[ -src16_linesize + (i-2)*src16_stride] + src16[ src16_linesize + (i-2)*src16_stride]) * 4 + + (src16[ -src16_linesize + (i-1)*src16_stride] + src16[ src16_linesize + (i-1)*src16_stride]) * 9 + + (src16[ -src16_linesize + (i )*src16_stride] + src16[ src16_linesize + (i )*src16_stride]) * 12 + + (src16[ -src16_linesize + (i+1)*src16_stride] + src16[ src16_linesize + (i+1)*src16_stride]) * 9 + + (src16[ -src16_linesize + (i+2)*src16_stride] + src16[ src16_linesize + (i+2)*src16_stride]) * 4 + + + src16[(i-2)*src16_stride] * 5 + + src16[(i-1)*src16_stride] * 12 + + src16[(i )*src16_stride] * 15 + + src16[(i+1)*src16_stride] * 12 + + src16[(i+2)*src16_stride] * 5) / 159; + } + dst16[i ] = src16[(i )*src16_stride]; + dst16[i + 1] = src16[(i + 1)*src16_stride]; + + dst16 += dst16_linesize; + src16 += src16_linesize; + } + memcpy(dst16, src16, w*2); dst16 += dst16_linesize; src16 += src16_linesize; + memcpy(dst16, src16, w*2); +} diff --git a/libavfilter/edge_common.h b/libavfilter/edge_common.h index 87c143f2b8..310d92a388 100644 --- a/libavfilter/edge_common.h +++ b/libavfilter/edge_common.h @@ -51,7 +51,13 @@ enum AVRoundedDirection { void ff_sobel(int w, int h, uint16_t *dst, int dst_linesize, int8_t *dir, int dir_linesize, - const uint8_t *src, int src_linesize); + const uint8_t *src, int src_linesize, int src_stride); + +void ff_sobel16(int w, int h, + uint16_t *dst, int dst_linesize, + int8_t *dir, int dir_linesize, + const uint8_t *src, int src_linesize, int src_stride); + /** * Filters rounded gradients to drop all non-maxima pixels in the magnitude image @@ -102,6 +108,10 @@ void ff_double_threshold(int low, int high, int w, int h, */ void ff_gaussian_blur(int w, int h, uint8_t *dst, int dst_linesize, - const uint8_t *src, int src_linesize); + const uint8_t *src, int src_linesize, int src_stride); + +void ff_gaussian_blur16(int w, int h, + uint8_t *dst, int dst_linesize, + const uint8_t *src, int src_linesize, int src_stride); #endif diff --git a/libavfilter/vf_blurdetect.c b/libavfilter/vf_blurdetect.c index 0e08ba96de..ed4fb29b31 100644 --- a/libavfilter/vf_blurdetect.c +++ b/libavfilter/vf_blurdetect.c @@ -285,10 +285,10 @@ static int blurdetect_filter_frame(AVFilterLink *inlink, AVFrame *in) // gaussian filter to reduce noise ff_gaussian_blur(w, h, filterbuf, w, - in->data[plane], in->linesize[plane]); + in->data[plane], in->linesize[plane], 1); // compute the 16-bits gradients and directions for the next step - ff_sobel(w, h, gradients, w, directions, w, filterbuf, w); + ff_sobel(w, h, gradients, w, directions, w, filterbuf, w, 1); // non_maximum_suppression() will actually keep & clip what's necessary and // ignore the rest, so we need a clean output buffer diff --git a/libavfilter/vf_edgedetect.c b/libavfilter/vf_edgedetect.c index 90390ceb3e..10397fb8dc 100644 --- a/libavfilter/vf_edgedetect.c +++ b/libavfilter/vf_edgedetect.c @@ -193,13 +193,13 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) /* gaussian filter to reduce noise */ ff_gaussian_blur(width, height, tmpbuf, width, - in->data[p], in->linesize[p]); + in->data[p], in->linesize[p], 1); /* compute the 16-bits gradients and directions for the next step */ ff_sobel(width, height, gradients, width, directions,width, - tmpbuf, width); + tmpbuf, width, 1); /* non_maximum_suppression() will actually keep & clip what's necessary and * ignore the rest, so we need a clean output buffer */