ข้อมูลภาพดิบจากกล้องเช่น 645 PRO

ครั้งหนึ่งฉันเคยถามคำถามนี้ไปแล้ว และฉันก็ได้รับคำตอบที่ดีเช่นกัน:

ฉันค้นหาฟอรัมนี้ขึ้น ๆ ลง ๆ แต่ไม่พบสิ่งที่ฉันต้องการจริงๆ ฉันต้องการรับข้อมูลภาพดิบจากกล้อง จนถึงตอนนี้ฉันพยายามดึงข้อมูลออกจาก imageDataSampleBuffer จากเมธอดนั้น captureStillImageAsynchronouslyFromConnection:completionHandler: และเขียนลงในวัตถุ NSData แต่นั่นไม่ได้ผล บางทีฉันอาจจะผิดเส้นทางหรือบางทีฉันแค่ทำผิด สิ่งที่ฉันไม่ต้องการคือต้องบีบอัดรูปภาพด้วยวิธีใดก็ตาม

วิธีง่าย ๆ คือใช้ jpegStillImageNSDataRepresentation: จาก AVCaptureStillImageOutput แต่อย่างที่ฉันบอกว่าฉันไม่ต้องการให้มันถูกบีบอัด

ขอบคุณ!

ข้อมูลภาพดิบจากกล้อง

ฉันคิดว่าฉันสามารถแก้ไขปัญหานี้ได้ แต่ในที่สุดฉันก็สังเกตเห็นว่าฉันต้องได้รับข้อมูลภาพดิบโดยตรงมากขึ้น ในลักษณะเดียวกับที่ทำใน "645 PRO"

645 PRO: RAW Redux

รูปภาพบนไซต์นั้นแสดงว่าได้รับข้อมูลดิบก่อนที่การบีบอัด JPEG จะเสร็จสิ้น นั่นคือสิ่งที่ฉันต้องการจะทำ ฉันเดาว่าฉันต้องแปลง imageDataSampleBuffer แต่ฉันไม่เห็นวิธีที่จะทำได้อย่างสมบูรณ์หากไม่มีการบีบอัด "645 PRO" ยังบันทึกรูปภาพใน TIFF ด้วย ดังนั้นฉันคิดว่ามันใช้ไลบรารีเพิ่มเติมอย่างน้อยหนึ่งไลบรารี

ฉันไม่ต้องการสร้างแอปรูปภาพ แต่ฉันต้องการคุณภาพที่ดีที่สุดเพื่อตรวจสอบคุณสมบัติบางอย่างในรูปภาพ

ขอบคุณ!

แก้ไข 1: หลังจากลองค้นหาในทิศทางต่างๆ มาสักระยะหนึ่งแล้ว ฉันจึงตัดสินใจอัปเดตสถานะ

เป้าหมายสุดท้ายของโปรเจ็กต์นี้คือการตรวจสอบคุณสมบัติบางอย่างในรูปภาพซึ่งจะเกิดขึ้นด้วยความช่วยเหลือของ opencv แต่จนกว่าแอปจะสามารถทำได้บนโทรศัพท์ ฉันกำลังพยายามดึงรูปภาพที่ไม่มีการบีบอัดเป็นส่วนใหญ่ออกจากโทรศัพท์เพื่อวิเคราะห์บนคอมพิวเตอร์

ดังนั้นฉันต้องการบันทึก "อินสแตนซ์ NSData ที่มีไบต์ BGRA ที่ไม่บีบอัดที่ส่งคืนจากกล้อง" ฉันสามารถรับโค้ดของ Brad Larson เป็นไฟล์ bmp หรือ TIFF ได้ อย่างที่ฉันพูดในความคิดเห็น ฉันลองใช้ opencv สำหรับสิ่งนี้ (มันจะจำเป็นอยู่แล้ว) แต่สิ่งที่ดีที่สุดที่ฉันทำได้คือเปลี่ยนให้เป็น UIImage ด้วยฟังก์ชันจาก การพูดคุยเรื่องคอมพิวเตอร์วิทัศน์

void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
cv::Mat frame(height, width, CV_8UC4, (void*)baseAddress);
UIImage *testImag = [UIImage imageWithMat:frame andImageOrientation:UIImageOrientationUp];
//imageWithMat... being the function from Computer Vision Talks which I can post if someone wants to see it

ImageMagick - แนวทาง

อีกสิ่งที่ฉันลองคือใช้ ImageMagick ตามที่แนะนำใน โพสต์อื่น . แต่ฉันไม่สามารถหาวิธีทำได้โดยไม่ใช้บางอย่างเช่น UIImagePNGRepresentationหรือ UIImageJPEGRepresentation

สำหรับตอนนี้ฉันกำลังพยายามทำอะไรบางอย่างกับ libtiff โดยใช้บทช่วยสอน.

อาจมีคนมีความคิดหรือรู้วิธีที่ง่ายกว่ามากในการแปลงวัตถุบัฟเฟอร์ของฉันให้เป็นรูปภาพที่ไม่มีการบีบอัด ขอขอบคุณล่วงหน้าอีกครั้ง!

แก้ไข 2:

ฉันพบบางสิ่งบางอย่าง! และฉันต้องบอกว่าฉันตาบอดมาก

void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
cv::Mat frame(height, width, CV_8UC4, (void*)baseAddress);

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"ocv%d.TIFF", picNum]];
const char* cPath = [filePath cStringUsingEncoding:NSMacOSRomanStringEncoding];

const cv::string newPaths = (const cv::string)cPath;

cv::imwrite(newPaths, frame);

ฉันแค่ต้องใช้ฟังก์ชัน imwrite จาก opencv วิธีนี้ฉันจะได้ไฟล์ TIFF ประมาณ 30 MB โดยตรงหลังจาก beyer-Polarization!


person thomketler    schedule 23.07.2012    source แหล่งที่มา
comment
ฉันพบคำตอบนี้ในการค้นหาประมาณ 10 วินาที: stackoverflow.com/a/10865206/96716   -  person David H    schedule 23.07.2012
comment
ขอบคุณดัสติน ฉันกลัวอะไรแบบนั้นอยู่แล้ว ฉันแค่หวังว่าจะมีคนให้คำแนะนำหรืออะไรสักอย่างแก่ฉัน และต้องขอบคุณ David H แต่ฉันได้ตรวจดูเรื่องนั้นแล้ว และมันไม่ได้ช่วยอะไรกรณีของฉันเลย หรืออย่างน้อยฉันก็คิดไม่ออกว่าต้องทำอย่างไร แต่ฉันขอบคุณสำหรับทุกคำใบ้!   -  person thomketler    schedule 23.07.2012


คำตอบ (4)


ว้าว โพสต์บล็อกนั้นมีอะไรพิเศษ มีคำพูดมากมายที่ระบุว่าได้รับไบต์บัฟเฟอร์ตัวอย่างที่ Apple ส่งคืนให้คุณจากภาพนิ่ง แนวทางของพวกเขาไม่มีอะไรแปลกใหม่เป็นพิเศษ และฉันก็รู้จักแอปพลิเคชั่นกล้องจำนวนหนึ่งที่ทำเช่นนี้

คุณสามารถรับไบต์ดิบที่ส่งคืนจากภาพถ่ายที่ถ่ายด้วย AVCaptureStillImageOutput โดยใช้โค้ดดังต่อไปนี้:

[photoOutput captureStillImageAsynchronouslyFromConnection:[[photoOutput connections] objectAtIndex:0] completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
    CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(imageSampleBuffer);
    CVPixelBufferLockBaseAddress(cameraFrame, 0);
    GLubyte *rawImageBytes = CVPixelBufferGetBaseAddress(cameraFrame);
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(cameraFrame);
    NSData *dataForRawBytes = [NSData dataWithBytes:rawImageBytes length:bytesPerRow * CVPixelBufferGetHeight(cameraFrame)];
    // Do whatever with your bytes

    CVPixelBufferUnlockBaseAddress(cameraFrame, 0);
}];

สิ่งนี้จะให้อินสแตนซ์ NSData แก่คุณซึ่งมีไบต์ BGRA ที่ไม่มีการบีบอัดที่ส่งคืนจากกล้อง คุณสามารถบันทึกสิ่งเหล่านี้ลงดิสก์หรือทำอะไรก็ได้ที่คุณต้องการ หากคุณต้องการประมวลผลไบต์ด้วยตนเองจริงๆ ฉันจะหลีกเลี่ยงค่าใช้จ่ายในการสร้าง NSData และทำงานกับอาร์เรย์ไบต์จากบัฟเฟอร์พิกเซล

person Brad Larson    schedule 23.07.2012
comment
ขอบคุณมากสำหรับความช่วยเหลือของคุณ. เป็นเรื่องดีที่รู้ว่าฉันไม่ได้เดินผิดทางเลย ฉันหวังว่าฉันจะไม่ทำให้คุณอดทน แต่คุณรู้วิธีง่ายๆ ในการเปลี่ยนสิ่งนี้ให้เป็นบิตแมปหรือไม่ ฉันกำลังคิดที่จะใช้ openCV ในลักษณะที่คล้ายกันในโพสต์อื่น ลิงก์ ฉันแค่อยากทราบว่าฉันขาดวิธีที่ง่ายกว่านี้ไปมากหรือไม่ และขอบคุณอีกครั้งที่ฉันชนกำแพงด้วยสิ่งนี้มาระยะหนึ่งแล้ว - person thomketler; 24.07.2012

ฉันสามารถแก้ไขมันได้ด้วย OpenCV ขอบคุณทุกคนที่ช่วยฉัน

void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
cv::Mat frame(height, width, CV_8UC4, (void*)baseAddress);

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"ocv%d.BMP", picNum]];
const char* cPath = [filePath cStringUsingEncoding:NSMacOSRomanStringEncoding];

const cv::string newPaths = (const cv::string)cPath;

cv::imwrite(newPaths, frame);

ฉันแค่ต้องใช้ฟังก์ชัน imwrite จาก opencv วิธีนี้ฉันได้รับไฟล์ BMP ประมาณ 24 MB โดยตรงหลังจากตัวกรองไบเออร์!

person thomketler    schedule 03.08.2012

ในขณะที่คำตอบหลักมาจาก Brad ที่ iOS: รับข้อมูลแบบพิกเซลต่อพิกเซลจากกล้อง ซึ่งเป็นองค์ประกอบสำคัญในการตอบกลับของ Brad ที่ไม่ชัดเจนโดยสิ้นเชิง มันถูกซ่อนอยู่ใน "เมื่อคุณกำหนดค่าเซสชันการจับภาพแล้ว..."

คุณต้องตั้งค่าเอาต์พุตที่ถูกต้องสำหรับ AVCaptureStillImageOutput ของคุณ

ตัวอย่างเช่น การตั้งค่า kCVPixelBufferPixelFormatTypeKey เป็น kCVPixelFormatType_420YpCbCr8BiPlanarFullRange จะทำให้คุณได้ YCbCr imageDataSampleBuffer ใน captureStillImageAsynchronouslyFromConnection:completionHandler: ซึ่งคุณสามารถปรับเปลี่ยนได้ตามที่ใจต้องการ

person Wildaker    schedule 23.07.2012
comment
สิ่งหนึ่งที่ต้องคำนึงถึง: kCVPixelBufferPixelFormatTypeKey เป็น int ดังนั้นคุณจะต้องล้อมมันด้วย NSNumber เมื่อเพิ่มลงในพจนานุกรมของคุณ นอกจากนี้ ภายใต้ ARC คุณจะต้องแปลงค่าจริงเป็น id ด้วยตนเอง - person FeifanZ; 02.08.2012

ดังที่ @Wildaker กล่าวไว้ เพื่อให้โค้ดเฉพาะใช้งานได้คุณต้องแน่ใจว่ากล้องส่งรูปแบบพิกเซลใดถึงคุณ โค้ดจาก @thomketler จะทำงานหากตั้งค่าเป็นรูปแบบ RGBA 32 บิต

นี่คือรหัสสำหรับค่าเริ่มต้น YUV จากกล้องโดยใช้ OpenCV:

cv::Mat convertImage(CMSampleBufferRef sampleBuffer)
{
    CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(sampleBuffer);
    CVPixelBufferLockBaseAddress(cameraFrame, 0);

    int w = (int)CVPixelBufferGetWidth(cameraFrame);
    int h = (int)CVPixelBufferGetHeight(cameraFrame);
    void *baseAddress = CVPixelBufferGetBaseAddressOfPlane(cameraFrame, 0);

    cv::Mat img_buffer(h+h/2, w, CV_8UC1, (uchar *)baseAddress);
    cv::Mat cam_frame;
    cv::cvtColor(img_buffer, cam_frame, cv::COLOR_YUV2BGR_NV21);
    cam_frame = cam_frame.t();

    //End processing
    CVPixelBufferUnlockBaseAddress( cameraFrame, 0 );

    return cam_frame;
}

cam_frame ควรมีเฟรม BGR แบบเต็ม ฉันหวังว่ามันจะช่วยได้

person G. Führ    schedule 13.01.2017