Windows Phone 8.1 图片裁剪

3

我是一名新手Windows Phone程序员。我正在尝试创建一个人脸识别应用程序。我的问题是:我无法正确地通过矩形裁剪掉检测到的人脸图像。

以下是原始图像和裁剪后的图像:https://onedrive.live.com/redir?resid=3F56C0D8DEC03C5B%21109

foreach (var r in faces)
{                                
    System.Windows.Shapes.Rectangle toAdd = new System.Windows.Shapes.Rectangle();                    
    TranslateTransform loc = new TranslateTransform();

    loc.X = r.X * _downsampleFactor / (double)w * cnvsFaceRegions.ActualWidth;
    loc.Y = r.Y * _downsampleFactor / (double)w * cnvsFaceRegions.ActualHeight;                     
    toAdd.RenderTransform = loc;
    toAdd.Width = r.Width * _downsampleFactor+50;
    toAdd.Height = r.Height * _downsampleFactor+50;
    toAdd.Stroke = new SolidColorBrush(Colors.Red);

    cnvsFaceRegions.Children.Add(toAdd);
    widthRectangle = toAdd.Width;
    heightRectangle = toAdd.Height;
    point1 = loc.X ;
    point2 = loc.Y ;

}

接下来我将裁剪图片:

 private  void  SaveScreenShots()            
 {             
   WriteableBitmap bmp = new WriteableBitmap((int)this.ActualWidth, (int)this.ActualHeight);           
   WriteableBitmap bmp2= CropImage(bmp,(int)point1, (int)point2, (int)widthRectangle, (int)heightRectangle);             
   bmp2.Render(this, null);
   byte[] bb = EncodeToJpeg(bmp2);
   bmp2.Invalidate();

   MemoryStream mem = new MemoryStream();
   bmp2.SaveJpeg(mem, bmp2.PixelWidth, bmp2.PixelHeight, 0, 100);
   mem.Seek(0, System.IO.SeekOrigin.Begin);

   if (mem != null)
   {

       MediaLibrary library = new MediaLibrary();
       try
       {

           pic = library.SavePicture("Mask_" + Guid.NewGuid().ToString(), mem);
           MaskPath = pic.GetPath();
           Deployment.Current.Dispatcher.BeginInvoke(() =>
           {
               MessageBoxResult result = MessageBox.Show("", "Saved successfully", MessageBoxButton.OK);

           });

       }
       catch (Exception ex)
       {
           MessageBox.Show("Unable to save the photo." + ex);

       }
   }     
        cameraViewer.NewCameraFrame += NewCameraFrame;
    }

裁剪功能:
 private static WriteableBitmap CropImage(WriteableBitmap source, int xOffset, int yOffset, int width, int height)
     {

         var sourceWidth = source.PixelWidth;
         var result = new WriteableBitmap(width, height);
         for (var x = 0; x <= height - 1; x++)
         {
             var sourceIndex = xOffset + (yOffset + x) * sourceWidth;
             var destinationIndex = x * width;
             Array.Copy(source.Pixels, sourceIndex, result.Pixels, destinationIndex, width);
         }
         return result;

     }

感谢您的帮助。

似乎你认为图片的尺寸与实际尺寸不符。在全屏截图中,矩形的尺寸是300x300,但裁剪后的图像尺寸是362x362。我建议你将WriteableBitmap source的宽度/高度与你期望的宽度/高度进行比较。 - meneses.pt
我拍了另一张照片并上传了它。裁剪后的图像与原始照片中的矩形具有相同的大小(362x362)。 - Fačko
屏幕截图中的矩形尺寸为300x300,而不是362x362。这就是我说你应该检查访问/创建的所有对象是否具有相同大小的原因。 - meneses.pt
是的,但那是之前的图片。我制作了另一张并上传到这里,分别命名为1.jpg和2.jpg。 https://onedrive.live.com/redir?resid=3F56C0D8DEC03C5B%21109 - Fačko
请纠正我如果我错了,但这里的问题似乎是偏移量。它正在使用正确的宽度和高度进行裁剪,但是它没有从xOffset和yOffset值开始,而是从0,0坐标开始。当您到达CropImage函数时,您能否调试您的代码并告诉我xOffset和yOffset的值? - meneses.pt
是的,宽度和高度都是正确的。我调试了我的代码,对于我现在上传的图片,xOffset=63,yOffset=140。 - Fačko
1个回答

0

你的 crop 实现不正确。

var sourceIndex = xOffset + (yOffset + x) * sourceWidth;

你想要一个与 Line 方程镜像的偏移量

y = mx + b;    // where y is your offset
               // m is your vertical position
               // x is your width
               // b is your starting horizontal position

所以你基本上是复制图像的一个水平部分,并将这些像素复制到缓冲区,重复此过程直到你有足够的部分。

完整实现:

private WriteableBitmap CropImage(WriteableBitmap source, int x, int y, int width, int height)
{
    // range check
    if (x < 0 || y < 0 || width <= 0 || height <= 0)
        return null;

    // create the bitmap
    WriteableBitmap dest = new WriteableBitmap(width, height);

    // calculate the starting offset
    int offset = (y * source.PixelWidth) + x;

    // copy each row of pixels from the starting y location to (y + height) with the width of width
    for (int i = 0; i < height; i++)
    {
        Array.Copy(source.Pixels, offset, dest.Pixels, i * width, width);
        offset += source.PixelWidth;
    }

    // return the crop image
    return dest;
}

其他参考资料

使用WriteableBitmap类裁剪图像的方法


1
我尝试使用这些函数,但仍然存在相同的问题。裁剪功能无法正确工作,我仍然只能看到矩形的一部分。 - Fačko
@Fačko 我向您保证上面的裁剪图像功能是正确的。我猜测您的程序流程现在有问题。例如,为什么您要先裁剪图像然后再渲染它呢?应该先渲染到图像,然后再进行裁剪。 - Chubosaurus Software
谢谢,问题出在我的程序流程上。当我首次渲染并裁剪图像后,它几乎完美运行。但是我必须将27添加到yOffset参数中以正确裁剪图像,但不知道为什么。WriteableBitmap bmp2 = CropImage2(bmp, (int)point1, (int)point2+27, (int)widthRectangle, (int)heightRectangle); - Fačko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接