CvInvoke.Canny() - дает разные результаты на разных компьютерах

при попытке выполнить некоторые бинарные манипуляции с одним и тем же файлом изображения, но на разных компьютерах (&мониторах), я получаю другой результат при использовании метода CvInvoke.Canny().
перед вызовом этого метода я использую несколько методов манипулирования, таких как: CvInvoke.Threshold() , CvInvoke.Erode() , CvInvoke.Dilate() и многое другое... результат всех этих действий всегда равен.
это просто когда я вызываю:

UMat inputImageUMAT = new Image<Gray, byte>(inputImageBitmap).ToUMat();
UMat imageUmat = new UMat();
CvInvoke.Threshold(imageInputUMAT, imageUmat, threshold, 255, 
Emgu.CV.CvEnum.ThresholdType.Binary);

// clear noises with Erode & Dilate:
CvInvoke.Erode(imageUmat, imageUmat, null, new Point(-1, -1), 1, 
BorderType.Constant, CvInvoke.MorphologyDefaultBorderValue);
CvInvoke.Dilate(imageUmat, imageUmat, null, new Point(-1, -1), 1, 
BorderType.Constant, CvInvoke.MorphologyDefaultBorderValue);

//use image pyr to remove noise:
UMat pyrDown = new UMat();
CvInvoke.PyrDown(imageUmat, pyrDown);
CvInvoke.PyrUp(pyrDown, imageUmat);

 // set cannyEdges to hold the outlines of the shapes detected in the image 
(according to threshold) 
UMat cannyEdges = new UMat();
CvInvoke.Canny(imageUmat, cannyEdges, threshold, threshold);

между выходными данными разных компьютеров всегда есть разница.
тем не менее, каждый компьютер всегда дает один и тот же результат - раз за разом.

что может быть причиной проблемы?
у меня должны быть одинаковые результаты везде...

p.s.
я использую слепок C#: EMGU.CV v3.3.0.2824

редактировать:
я взял исходный файл: оригинал
и пропустил все манипуляции в пути и сразу выполнил Canny:

UMat inputImageUMAT = new UMat(fileName, ImreadModes.Grayscale);
UMat cannyEdges = new UMat();
CvInvoke.Canny(imageInputUMAT, cannyEdges, threshold, threshold, 3, true);
cannyEdges.Save(outputFileName);

результат с порогом 210 машина 1: result_1
результат с порогом 210 машина 2: result_2
-- разница в 1 пиксель между двумя результатами


person RedHat    schedule 01.02.2018    source источник
comment
когда я меняю код на: CvInvoke.Canny(imageUmat, cannyEdges, threshold, threshold, 3 , true); - разница все еще есть.   -  person RedHat    schedule 04.02.2018
comment
Можете ли вы ограничить свой код ТОЛЬКО вызовом CvInvoke.Canny для гарантированно одинаковых изображений (без сжатия jpg, только форматы без потерь) и показать нам 2 изображения с разницей?   -  person Dmitrii Z.    schedule 04.02.2018
comment
Также меняется ли результат от одного прогона к другому на одной и той же машине?   -  person Dmitrii Z.    schedule 04.02.2018
comment
на каждой машине результаты всегда одинаковы.   -  person RedHat    schedule 04.02.2018
comment
Я не уверен, что понял, о чем ты просил. я сохранял UMAT в .bmp после каждого шага и сравнивал его с помощью инструмента beyond compare. я не знаю, как загрузить разные файлы, но я проверю это.   -  person RedHat    schedule 04.02.2018
comment
Различные результаты могут быть вызваны различными реализациями декодеров. Чтобы убедиться, что это не так, я рекомендую не использовать сжатие входных файлов. Поэтому просто сохраните свое изображение перед вызовом Canny и передайте результат в Canny на 2 машинах, сохраните вывод как изображение и поместите их в свой вопрос.   -  person Dmitrii Z.    schedule 04.02.2018
comment
большое спасибо @DmitriiZ. - я добавил файлы и пропустил все сжатие по пути - есть предложения по разнице?   -  person RedHat    schedule 04.02.2018
comment
@DmitriiZ. - нашел! не могу на самом деле понять wtf, но работает отлично!   -  person RedHat    schedule 05.02.2018


Ответы (2)


Я написал в поддержку EMGU, и вот их удивительный ответ:

Я просмотрел ваш код, и он использует UMat. Это означает, что код будет использовать OpenCL (GPU) для ускорения обработки, когда он доступен, и вернется к CPU для рабочей станции, где нет совместимого драйвера/устройства OpenCL.
Я подозреваю, что результат, полученный OpenCL путь немного отличается от пути процессора. Можете ли вы следующую строку перед вызовом любой функции Emgu CV в вашем коде и проверьте, делает ли это результат согласованным на всех машинах:

CvInvoke.UseOpenCL = false

Приведенный выше код отключит OpenCL и заставит весь код выполняться на процессоре.

не удивительно - они правы. это действительно решило проблему.

person RedHat    schedule 06.02.2018

ОК.
Не могу сказать, что понял причину проблемы на 100%, но у меня определенно получилось стабильно на всех компьютерах.
дело в том, что сначала я использовал статический метод CvInvoke.Canny() и отправил ввод и вывод Umat - он вероятно не знал наверняка, какое изображение является исходным, а затем (путем доступа к некоторым windows dll или приоритетам или чему-то еще?) это приводило к принятию разных решений по каждому компьютера, и поэтому разные Umat переводы приводили к разным результатам.
(...может быть)

НО
когда я загрузил входное изображение в Image<Gray, Byte> и использовал собственный метод Canny (а также другие методы) - все стабильно стабильно и независимо от того, на каком компьютере он работает on.
поэтому рабочий код:

UMat inputImageUMAT = new Image<Gray, byte>(inputFileName).ToUMat();
Image<Gray, Byte> binaryImage = inputImageUMAT.ToImage<Gray,Byte>().ThresholdBinary(new Gray(threshold), new Gray(255));
binaryImage = binaryImage.Erode(1);
binaryImage = binaryImage.Dilate(1);
binaryImage = binaryImage.PyrDown();
binaryImage = binaryImage.PyrUp();
binaryImage = binaryImage.Canny(1, 0, 3, true);
person RedHat    schedule 05.02.2018