2014-07-15 17 views
9

Chúng tôi có một vấn đề OpenCV mở (và văn bản) đường dẫn tập tin có chứa các ký tự không Ascii trên Windows. tôi thấy câu hỏi OpenCV imread with foreign charactersimread(openCV),QString unicodes nhưng vẫn không hiểu một cách đúng đắn của việc giải quyết vấn đề.opencv imread() trên Windows cho tên tập tin ASCII

Khi đến nay tôi khi tôi nhìn thấy trong mã nguồn OpenCV, nó sử dụng fopen ngay cả trên Windows (thay vì _wfopen) và afaik fopen không xử lý các ký tự không ascii trên Windows. Từ những câu hỏi trên tôi thấy rằng có thể có một số mẹo sử dụng QStrings, nhưng nếu nó hoạt động chính xác thì nó sẽ làm gì? Làm thế nào nó chuyển đổi một chuỗi unicode thành một mảng ký tự mà sẽ được chấp nhận bởi fopen() của Windows?

P.S. Chúng tôi không sử dụng QT

Cảm ơn trước!

Trả lời

8

Cách để thực hiện điều này mà không cần hack mã nguồn OpenCV là sử dụng _wfopen (như đề nghị Remy) để đọc toàn bộ tệp vào bộ nhớ đệm. Sau đó sử dụng chức năng của OpenCV imdecode để tạo ra một cv::Mat từ đệm đó. Bạn cũng có thể làm ngược lại, nếu cần - ví dụ: sử dụng imencode để ghi ảnh vào bộ nhớ đệm, sau đó sử dụng _wfopen để mở tệp có tên UNICODE và ghi bộ đệm vào nó (cách khác, bạn chỉ có thể imwrite) vào một tệp tạm thời và sau đó di chuyển/đổi tên nó bằng cách sử dụng hàm API thích hợp).

+1

Cảm ơn! Tôi có thể xác nhận rằng giải pháp này hoạt động cho chúng tôi – Vyacheslav

+0

Tôi có cùng một vấn đề và tôi muốn thử giải pháp của bạn. Tôi có thể nhận được một 'FILE *' trên tập tin của tôi với 'wfopen' nhưng sau đó tôi không biết làm thế nào để sử dụng đúng' imdecode' để có được một 'cv :: Mat' từ đó. Ngoài ra: không OpenCV vẫn không hỗ trợ phi ASCII tên tập tin nguyên bản, cũng trong phiên bản 3.0? PS: là có thể có một cách dễ dàng hơn nhưng vẫn hiệu quả nếu tôi _do_ sử dụng Qt (Tôi có nghĩa là không đọc 'QImage' s và chuyển đổi sau đó)? – user1488118

3

Phiên bản fopen() của Microsoft trong Visual Studio hỗ trợ cờ chế độ phi tiêu chuẩn css cho phép đọc/ghi dữ liệu Unicode, nhưng không hỗ trợ tên tệp Unicode. Bạn phải sử dụng _wfopen() cho rằng, do đó bạn sẽ phải tinh chỉnh mã nguồn của OpenCV để bạn có thể vượt qua trong một tên tập tin Unicode và mở nó với _wfopen() thay vì fopen().

1

đây giải pháp của tôi sử dụng std::ifstream:

std::ifstream file(path.toStdWString(), std::iostream::binary); 
if (!file.good()) { 
    return cv::Mat(); 
} 
file.exceptions(std::ifstream::badbit | std::ifstream::failbit | std::ifstream::eofbit); 
file.seekg(0, std::ios::end); 
std::streampos length(file.tellg()); 
std::vector<char> buffer(static_cast<std::size_t>(length)); 
if (static_cast<std::size_t>(length) == 0) { 
    return cv::Mat(); 
} 
file.seekg(0, std::ios::beg); 
try { 
    file.read(buffer.data(), static_cast<std::size_t>(length)); 
} catch (...) { 
    return cv::Mat(); 
} 
file.close(); 
cv::Mat image = cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR); 
return image; 

Hoặc một chút ngắn hơn sử dụng Qt:

QFile file(path); 
std::vector<char> buffer; 
buffer.resize(file.size()); 
if (!file.open(QIODevice::ReadOnly)) { 
    return cv::Mat(); 
} 
file.read(buffer.data(), file.size()); 
file.close(); 
cv::Mat image = cv::imdecode(buffer, CV_LOAD_IMAGE_COLOR); 
return image; 
1

Hãy thử điều này:

cv::Mat ReadImage(const wchar_t* filename) 
{ 
    FILE* fp = _wfopen(filename, L"rb"); 
    if (!fp) 
    { 
     return Mat::zeros(1, 1, CV_8U); 
    } 
    fseek(fp, 0, SEEK_END); 
    long sz = ftell(fp); 
    char* buf = new char[sz]; 
    fseek(fp, 0, SEEK_SET); 
    long n = fread(buf, 1, sz, fp); 
    _InputArray arr(buf, sz); 
    Mat img = imdecode(arr, CV_LOAD_IMAGE_COLOR); 
    delete[] buf; 
    fclose(fp); 
    return img; 
} 
Các vấn đề liên quan