0

畳み込みカーネルで pix をフィルタリングしたいのですが、バイアスがあり、Leptonica API を使用してバイアスを「エミュレート」する方法がわかりません。

これまでのところ、私は持っています:

PIX* pixs = pixRead("file.png");
L_KERNEL* kel = kernelCreatFromString( 7, 7, 3, 3, "..." );

PIX* pixd = pixConvolve( pixs, kel, 8, 1 );

古典的な「バイアス」をエミュレートする方法はありますか?pixConvolve の前後に画像の各ピクセルにその値を追加しようとしましたが、結果はほとんどの画像処理ソフトウェアで観察されるものではありません。

4

2 に答える 2

1

「バイアス」とは、すべてのピクセル値が非負になるように結果をシフトすることを想定しています。

pixConvolve() の注意点では、負の出力を避けるために絶対値を取ると書かれています。また、負の値を維持したい場合は、代わりに fpixConvolve() を使用してください。これは FPix で動作し、FPix を生成します。

クリッピングなしで偏った結果が必要な場合は、一般に次のことを行う必要があります。

  • (1) pixConvertToFpix() -- FPix に変換
  • (2) fpixConvolve() -- FPix で畳み込みを行い、FPix を生成します
  • (3) fpixGetMin() -- すべての値を非ゼロにするために必要なバイアスを決定します
  • (4) fpixAddMultConstant() -- FPix にバイアスを追加します
  • (5) fpixGetMax() -- 最大値を見つけます。> 255 の場合、それを表すには 16 bpp の Pix が必要です
  • (6) fpixConvertToPix -- pix に戻す

おそらく、レプトニカのメンテナー (私) は、これをシンプルなインターフェースにまとめるべきです ;-)

OK、ここに関数があります。上で書いた概要に従って、これらの畳み込みを行うのに十分な柔軟性を与えるはずです。

 /*!
 *  pixConvolveWithBias()
 *              Input:  pixs (8 bpp; no colormap)
 *              kel1
 *              kel2  (can be null; use if separable)
 *              force8 (if 1, force output to 8 bpp; otherwise, determine
 *                      output depth by the dynamic range of pixel values)
 *              &bias (<return> applied bias)
 *      Return: pixd (8 or 16 bpp)
 *
 *  Notes:
 *      (1) This does a convolution with either a single kernel or
 *          a pair of separable kernels, and automatically applies whatever
 *          bias (shift) is required so that the resulting pixel values
 *          are non-negative.
 *      (2) If there are no negative values in the kernel, a normalized
 *          convolution is performed, with 8 bpp output.
 *      (3) If there are negative values in the kernel, the pix is
 *          converted to an fpix, the convolution is done on the fpix, and
 *          a bias (shift) may need to be applied.
 *      (4) If force8 == TRUE and the range of values after the convolution
 *          is > 255, the output values will be scaled to fit in
 *          [0 ... 255].
 *          If force8 == FALSE, the output will be either 8 or 16 bpp,
 *          to accommodate the dynamic range of output values without
 *          scaling.
 */
PIX *
pixConvolveWithBias(PIX       *pixs,
                    L_KERNEL  *kel1,
                    L_KERNEL  *kel2,
                    l_int32    force8,
                    l_int32   *pbias)
{
l_int32    outdepth;
l_float32  min1, min2, min, minval, maxval, range;
FPIX      *fpix1, *fpix2;
PIX       *pixd;

    PROCNAME("pixConvolveWithBias");

    if (!pixs || pixGetDepth(pixs) != 8)
        return (PIX *)ERROR_PTR("pixs undefined or not 8 bpp", procName, NULL);
    if (pixGetColormap(pixs))
        return (PIX *)ERROR_PTR("pixs has colormap", procName, NULL);
    if (!kel1)
        return (PIX *)ERROR_PTR("kel1 not defined", procName, NULL);

        /* Determine if negative values can be produced in convolution */
    kernelGetMinMax(kel1, &min1, NULL);
    min2 = 0.0;
    if (kel2)
        kernelGetMinMax(kel2, &min2, NULL);
    min = L_MIN(min1, min2);

    if (min >= 0.0) {
        if (!kel2)
            return pixConvolve(pixs, kel1, 8, 1);
        else
            return pixConvolveSep(pixs, kel1, kel2, 8, 1);
    }

        /* Bias may need to be applied; convert to fpix and convolve */
    fpix1 = pixConvertToFPix(pixs, 1);
    if (!kel2)
        fpix2 = fpixConvolve(fpix1, kel1, 1);
    else
        fpix2 = fpixConvolveSep(fpix1, kel1, kel2, 1);
    fpixDestroy(&fpix1);

       /* Determine the bias and the dynamic range.
         * If the dynamic range is <= 255, just shift the values by the
         * bias, if any.
         * If the dynamic range is > 255, there are two cases:
         *    (1) the output depth is not forced to 8 bpp ==> outdepth = 16
         *    (2) the output depth is forced to 8 ==> linearly map the
         *        pixel values to [0 ... 255].  */
    fpixGetMin(fpix2, &minval, NULL, NULL);
    fpixGetMax(fpix2, &maxval, NULL, NULL);
    range = maxval - minval;
    *pbias = (minval < 0.0) ? -minval : 0.0;
    fpixAddMultConstant(fpix2, *pbias, 1.0);  /* shift: min val ==> 0 */
    if (range <= 255 || !force8) {  /* no scaling of output values */
        outdepth = (range > 255) ? 16 : 8;
    } else {  /* scale output values to fit in 8 bpp */
        fpixAddMultConstant(fpix2, 0.0, (255.0 / range));
        outdepth = 8;
    }

        /* Convert back to pix; it won't do any clipping */
    pixd = fpixConvertToPix(fpix2, outdepth, L_CLIP_TO_ZERO, 0);
    fpixDestroy(&fpix2);

    return pixd;
}
于 2012-07-09T20:16:13.380 に答える
0

ダンの入力に基づいて必要なソリューションを次に示します。

/*!
 *  pixConvolveWithBias()
 *              Input:  pixs (8 bpp; no colormap)
 *              kel1
 *              kel2  (can be null; use if separable)
 *              outdepth (of pixd: 8, 16 or 32)
 *              normflag (1 to normalize kernel to unit sum; 0 otherwise)
 *              bias
 *      Return: pixd
 *
 *  Notes:
 *      (1) This does a convolution with either a single kernel or
 *          a pair of separable kernels, and automatically applies whatever
 *          bias (shift) is required so that the resulting pixel values
 *          are non-negative.
 *      (2) If there are no negative values in the kernel, a convolution 
 *          is performed and bias added.
 *      (3) If there are negative values in the kernel, the pix is
 *          converted to an fpix, the convolution is done on the fpix, and
 *          a bias (shift) is applied.
 */
PIX *
pixConvolveWithBias(PIX       *pixs,
                    L_KERNEL  *kel1,
                    L_KERNEL  *kel2,
                    l_int32    outdepth,
                    l_int32    normflag,
                    l_int32    bias)
{
l_float32  min1, min2, min, minval, maxval, range;
FPIX      *fpix1, *fpix2;
PIX       *pixd;

    PROCNAME("pixConvolveWithBias");

    if (!pixs || pixGetDepth(pixs) != 8)
        return (PIX *)ERROR_PTR("pixs undefined or not 8 bpp", procName, NULL);
    if (pixGetColormap(pixs))
        return (PIX *)ERROR_PTR("pixs has colormap", procName, NULL);
    if (!kel1)
        return (PIX *)ERROR_PTR("kel1 not defined", procName, NULL);

        /* Determine if negative values can be produced in convolution */
    kernelGetMinMax(kel1, &min1, NULL);
    min2 = 0.0;
    if (kel2)
        kernelGetMinMax(kel2, &min2, NULL);
    min = L_MIN(min1, min2);

    if (min >= 0.0) {
        if (!kel2)
            pixd = pixConvolve(pixs, kel1, outdepth, normflag);
        else
            pixd = pixConvolveSep(pixs, kel1, kel2, outdepth, normflag);

        pixAddConstantGray(pixd, bias);
    } else {

          /* Bias may need to be applied; convert to fpix and convolve */
      fpix1 = pixConvertToFPix(pixs, 1);
      if (!kel2)
          fpix2 = fpixConvolve(fpix1, kel1, normflag);
      else
          fpix2 = fpixConvolveSep(fpix1, kel1, kel2, normflag);
      fpixDestroy(&fpix1);

      fpixAddMultConstant(fpix2, bias, 1.0);

      pixd = fpixConvertToPix(fpix2, outdepth, L_CLIP_TO_ZERO, 0);
      fpixDestroy(&fpix2);

    }

    return pixd;
}
于 2012-07-10T12:30:18.887 に答える