拍摄的照片有竖条纹

Captured photo has vertical stripes

我正在使用 WinRT Mediacapture class 拍摄照片,但是当我拍照时出现奇怪的透明条纹,这有点难以解释所以这里有一些照片:

捕获图片之前(预览)

拍照后

我在这里看到其他人也有同样的问题(比如 here,但他们的解决方案似乎对我不起作用。(要么没有结果,要么照片弄乱了向上)

我用来设置分辨率的代码:

System.Collections.Generic.IEnumerable<VideoEncodingProperties> available_resolutions = captureManager.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo).Select(x => x as VideoEncodingProperties);

foreach (VideoEncodingProperties resolution in available_resolutions)
{
     if (resolution != null && resolution.Width == 640 && resolution.Height == 480) //(resolution.Width==1920 && resolution.Height==1080) //resolution.Width==640 && resolution.Height==480)
     {
           await captureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.Photo, resolution);
     }
}

我用来拍照的代码:

private async Task<BitmapImage> ByteArrayToBitmapImage(byte[] byteArray)
    {
        var bitmapImage = new BitmapImage();

        using (var stream = new InMemoryRandomAccessStream())
        {
            await stream.WriteAsync(byteArray.AsBuffer());
            stream.Seek(0);

            await bitmapImage.SetSourceAsync(stream);

            await stream.FlushAsync();
        }

        return bitmapImage;
    }

    /// <summary>
    /// Relayed Execute method for TakePictureCommand.
    /// </summary>
    async void ExecuteTakePicture()
    {
        System.Diagnostics.Debug.WriteLine("Started making picture");
        DateTime starttime = DateTime.Now;

        ImageEncodingProperties format = ImageEncodingProperties.CreateJpeg();

        using (var imageStream = new InMemoryRandomAccessStream())
        {
            await captureManager.CapturePhotoToStreamAsync(format, imageStream);

            //Compresses the image if it exceedes the maximum file size
            imageStream.Seek(0);

            //Resize the image if needed
            uint maxImageWidth = 640;
            uint maxImageHeight = 480;

            if (AvatarPhoto)
            {
                maxImageHeight = 200;
                maxImageWidth = 200;

                //Create a BitmapDecoder from the stream
                BitmapDecoder resizeDecoder = await BitmapDecoder.CreateAsync(imageStream);

                if (resizeDecoder.PixelWidth > maxImageWidth || resizeDecoder.PixelHeight > maxImageHeight)
                {
                    //Resize the image if it exceedes the maximum width or height
                    WriteableBitmap tempBitmap = new WriteableBitmap((int)resizeDecoder.PixelWidth, (int)resizeDecoder.PixelHeight);
                    imageStream.Seek(0);
                    await tempBitmap.SetSourceAsync(imageStream);
                    WriteableBitmap resizedImage = tempBitmap.Resize((int)maxImageWidth, (int)maxImageHeight, WriteableBitmapExtensions.Interpolation.Bilinear);
                    tempBitmap = null;

                    //Assign to imageStream the resized WriteableBitmap
                    await resizedImage.ToStream(imageStream, BitmapEncoder.JpegEncoderId);
                    resizedImage = null;
                }

                //Converts the final image into a Base64 String
                imageStream.Seek(0);
            }

            //Converts the final image into a Base64 String
            imageStream.Seek(0);

            BitmapDecoder decoder = await BitmapDecoder.CreateAsync(imageStream);

            PixelDataProvider pixels = await decoder.GetPixelDataAsync();
            byte[] bytes = pixels.DetachPixelData();

            //Encode image
            InMemoryRandomAccessStream encoded = new InMemoryRandomAccessStream();
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, encoded);

            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Ignore, maxImageWidth, maxImageHeight, decoder.DpiX, decoder.DpiY, bytes);

            //Rotate the image based on the orientation of the camera
            if (currentOrientation == DisplayOrientations.Portrait)
            {
                encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees;
            }
            else if (currentOrientation == DisplayOrientations.LandscapeFlipped)
            {
                encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise180Degrees;
            }

            if (FrontCam)
            {
                if (currentOrientation == DisplayOrientations.Portrait)
                {
                    encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise270Degrees;
                }
                else if (currentOrientation == DisplayOrientations.LandscapeFlipped)
                {
                    encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise180Degrees;
                }
            }

            await encoder.FlushAsync();
            encoder = null;

            //Read bytes
            byte[] outBytes = new byte[encoded.Size];
            await encoded.AsStream().ReadAsync(outBytes, 0, outBytes.Length);

            encoded.Dispose();
            encoded = null;

            //Create Base64
            image = await ByteArrayToBitmapImage(outBytes);
            System.Diagnostics.Debug.WriteLine("Pixel width: " + image.PixelWidth + " height: " + image.PixelHeight);
            base64 = Convert.ToBase64String(outBytes);

            Array.Clear(outBytes, 0, outBytes.Length);
            await imageStream.FlushAsync();
            imageStream.Dispose();
        }

        DateTime endtime = DateTime.Now;
        TimeSpan span = (endtime - starttime);

        //Kind of a hacky way to prevent high RAM usage and even crashing, remove when overal RAM usage has been lowered
        GC.Collect();

        System.Diagnostics.Debug.WriteLine("Making the picture took: " + span.Seconds + " seconds");

        if (image != null)
        {
            RaisePropertyChanged("CapturedImage");

            //Tell both UsePictureCommand and ResetCommand that the situation has changed.
            ((RelayedCommand)UsePictureCommand).RaiseCanExecuteChanged();
            ((RelayedCommand)ResetCommand).RaiseCanExecuteChanged();
        }
        else
        {
            throw new InvalidOperationException("Imagestream is not valid");
        }
    }

如果有更多需要的信息欢迎评论,我会尽快发布,感谢阅读。

预览的纵横比必须与拍摄照片的纵横比相匹配,否则您会在拍摄中得到类似的伪像(尽管它实际上取决于驱动程序的实现,因此它可能因设备而异到设备)。

  1. MediaStream.VideoPreview 上使用 MediaCapture.VideoDeviceController.GetMediaStreamProperties() 方法。
  2. 获取结果 VideoEncodingProperties,并使用宽度和高度计算纵横比。
  3. MediaStream.Photo 上调用 MediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(),找出哪些长宽比匹配(我建议使用公差值,例如 0.015f 可能不错)
  4. 在符合要求的选项中,选择更适合您需求的一项,例如通过关注总分辨率 W * H
  5. 通过在 MediaStream.Photo 上调用 MediaCapture.VideoDeviceController.SetMediaStreamPropertiesAsync() 并传递所需的编码属性来应用您的选择。

更多信息见this thread. An SDK sample is available here