Windows phone 8.1 裁剪图像

Posted

技术标签:

【中文标题】Windows phone 8.1 裁剪图像【英文标题】:Windows phone 8.1 crop Image 【发布时间】:2014-11-17 13:22:53 【问题描述】:

我是 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 的宽度/高度与您期望的宽度/高度进行比较。 我又拍了一张照片上传了。裁剪后的图像与原始照片中的矩形具有相同的大小 (362x362)。 截图中的矩形是300x300,不是362x362。这就是为什么我说您应该检查您正在访问/创建的所有对象是否具有相同的大小。 是的,但它是以前的图像。我又做了一个,在这里上传为 1.jpg 和 2.jpg onedrive.live.com/redir?resid=3F56C0D8DEC03C5B%21109 如果我错了,请纠正我,但这里的问题似乎是偏移量。它以正确的宽度和高度进行裁剪,但不是从 xOffset 和 yOffset 值开始,而是从 0,0 坐标开始。当你到达 CropImage 函数时,你能调试你的代码并告诉我 xOffset 和 yOffset 的值吗? 【参考方案1】:

您的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;


其他参考文献

How to Crop an Image using the WriteableBitmap class

【讨论】:

我尝试使用这些功能,但仍然有同样的问题。裁剪功能无法正常工作,我仍然只能看到 Rectangle 的一部分。 @Fačko 我向你保证上面的裁剪图像功能是正确的。我猜你的程序流程现在是问题所在。例如,为什么要裁剪图像然后渲染它?它应该先渲染到图像上,然后裁剪。 谢谢,问题出在我的程序流程中。当我第一次渲染和裁剪图像之后,它几乎可以完美运行。但是我必须在 yOffset 参数中添加 27 才能正确裁剪图像并且不知道为什么。 WriteableBitmap bmp2 = CropImage2(bmp, (int)point1, (int)point2+27, (int)widthRectangle, (int)heightRectangle);

以上是关于Windows phone 8.1 裁剪图像的主要内容,如果未能解决你的问题,请参考以下文章

Windows phone 8.1 裁剪矩形

在 windows phone 8.1 中将 Base64String 图像显示为 MapIcon 图像

带有图像标签的 Binging 字符串 - Windows Phone 8.1 UWP

具有多个页面的 Windows Phone 8.1 自定义控件

如何在 Windows Phone 8.1 上从数据库中获取图像并将其显示为字节数组

如何在 Windows Phone 8.1 的列表视图中更新 <image> 的图像