Ваши три строки
Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();
targetTexture.ReadPixels(new Rect(0, 0, cameraResolution.width, cameraResolution.height), 0, 0);
targetTexture.Apply();
не имеет особого смысла для меня. Texture2D.ReadPixels предназначен для создания Снимка экрана , чтобы вы перезаписывали текстуру, которую вы только что получили от PhotoCapture
, со скриншотом? (Также с неправильными размерами, так как разрешение камеры очень вероятно! = Разрешение экрана.)
Это также причина для
Как написано в комментариях, разница между использованием этих трех строк и не в том, что сохраненная фотография имеет черный фон + AR-GUI.
После выполнения
photoCaptureFrame.UploadImageDataToTexture(targetTexture);
у вас уже есть Texture2D
, полученный от PhotoCapture
в targetTexture
.
Я думаю, что вы, вероятно, перепутали это с Texture2D.GetPixels , который используется для получения данных пикселей данного Texture2D
.
Я хотел бы обрезать захваченное фото из центра в конце и думаю, что, возможно, это возможно с этой строкой кода? Начало нового прямоугольника с пикселями, отличными от 0, 0)
На самом деле вы хотите обрезать полученные Texture2D
из центра, как вы упомянули в комментариях. Вы можете сделать это, используя GetPixels (int x, int y, int blockWidth, int blockHeight, int miplevel) , который используется для вырезания определенной области заданного Texture2D
public static Texture2D CropAroundCenter(Texture2D input, Vector2Int newSize)
{
if(input.width < newSize.x || input.height < newSize.y)
{
Debug.LogError("You can't cut out an area of an image which is bigger than the image itself!", this);
return null;
}
// get the pixel coordinate of the center of the input texture
var center = new Vector2Int(input.width / 2, input.height / 2);
// Get pixels around center
// Get Pixels starts width 0,0 in the bottom left corner
// so as the name says, center.x,center.y would get the pixel in the center
// we want to start getting pixels from center - half of the newSize
//
// than from starting there we want to read newSize pixels in both dimensions
var pixels = input.GetPixels(center.x - newSize.x / 2, center.y - newSize.y / 2, newSize.x, newSize.y, 0);
// Create a new texture with newSize
var output = new Texture2D(newSize.x, newSize.y);
output.SetPixels(pixels);
output.Apply();
return output;
}
для (надеюсь) лучшего понимания, это иллюстрация того, что делает здесь перегрузка GetPixels
с данными значениями:

и чем его использовать в
private void OnCapturedPhotoToMemory(PhotoCapture.PhotoCaptureResult result, PhotoCaptureFrame photoCaptureFrame)
{
// Copy the raw image data into the target texture
photoCaptureFrame.UploadImageDataToTexture(targetTexture);
// for example take only half of the textures width and height
targetTexture = CropAroundCenter(targetTexture, new Vector2Int(targetTexture.width / 2, targetTexture.height / 2);
byte[] bytes = targetTexture.EncodeToPNG();
string filename = FileName(Convert.ToInt32(targetTexture.width), Convert.ToInt32(targetTexture.height));
//save to folder under assets
File.WriteAllBytes(Application.streamingAssetsPath + "/Snapshots/" + filename, bytes);
Debug.Log("The picture was uploaded");
// Deactivate the camera
photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
}
Или вы можете сделать это метод расширения в отдельном static class
как
public static class Texture2DExtensions
{
public static void CropAroundCenter(this Texture2D input, Vector2Int newSize)
{
if (input.width < newSize.x || input.height < newSize.y)
{
Debug.LogError("You can't cut out an area of an image which is bigger than the image itself!");
return;
}
// get the pixel coordinate of the center of the input texture
var center = new Vector2Int(input.width / 2, input.height / 2);
// Get pixels around center
// Get Pixels starts width 0,0 in the bottom left corner
// so as the name says, center.x,center.y would get the pixel in the center
// we want to start getting pixels from center - half of the newSize
//
// than from starting there we want to read newSize pixels in both dimensions
var pixels = input.GetPixels(center.x - newSize.x / 2, center.y - newSize.y / 2, newSize.x, newSize.y, 0);
// Resize the texture (creating a new one didn't work)
input.Resize(newSize.x, newSize.y);
input.SetPixels(pixels);
input.Apply(true);
}
}
и используйте его вместо
targetTexture.CropAroundCenter(new Vector2Int(targetTexture.width / 2, targetTexture.height / 2));
Примечание:
UploadImageDataToTexture : Вы можете использовать этот метод, только если вы указали формат BGRA32 в CameraParameters.
К счастью, вы все равно используете это;)
Имейте в виду, что эта операция будет выполняться в главном потоке и, следовательно, будет медленной.
Однако единственной альтернативой будет CopyRawImageDataIntoBuffer и генерирование текстуры в другом потоке или во внешнем, так что я бы сказал, что можно остаться с UploadImageDataToTexture
;)
и
Захваченное изображение также появится перевернуто на HoloLens. Вы можете переориентировать изображение с помощью пользовательского шейдера.
при переворачивании они на самом деле означают, что Y-Axis
текстуры вверх ногами. X-Axis
правильно.
Для переворачивания текстуры по вертикали вы можете использовать второй метод расширения:
public static class Texture2DExtensions
{
public static void CropAroundCenter(){....}
public static void FlipVertically(this Texture2D texture)
{
var pixels = texture.GetPixels();
var flippedPixels = new Color[pixels.Length];
// These for loops are for running through each individual pixel and
// write them with inverted Y coordinates into the flippedPixels
for (var x = 0; x < texture.width; x++)
{
for (var y = 0; y < texture.height; y++)
{
var pixelIndex = x + y * texture.width;
var flippedIndex = x + (texture.height - 1 - y) * texture.width;
flippedPixels[flippedIndex] = pixels[pixelIndex];
}
}
texture.SetPixels(flippedPixels);
texture.Apply();
}
}
и используйте его как
targetTexture.FlipVertically();
Результат: (Я использовал FlipVertically и обрезал до половины размера каждую секунду для этого примера и данной текстуры, но он должен работать одинаково для снятого изображения.)

Источник изображения: http://developer.vuforia.com/sites/default/files/sample-apps/targets/imagetargets_targets.pdf
Update
К вашей проблеме с кнопкой:
Не использовать
if (Input.GetKey("k") || Input.GetKey("k"))
Прежде всего, вы проверяете одно и то же условие дважды. И затем GetKey
запускает каждый кадр , пока клавиша остается нажатой. Вместо этого используйте
if (Input.GetKeyDown("k"))
, который срабатывает только один раз. Я думаю, что была проблема с Vuforia и PhotoCapture, так как ваша оригинальная версия запускалась так часто, и, возможно, у вас были некоторые параллельные процессы PhotoCapture ...