c++ - Resizing the image in C# and sending it to OpenCV results in distorted image -
this follow-up question related this one.
 basically, have dll uses opencv image manipulation.
 there 2 methods, 1 accepting image-path, , other 1 accepting cv::mat.
 1 working image-path works fine.
 1 accepts image problematic.   
here method accepts filename(dll):   
cdll2_api void classify(const char * img_path, char* out_result, int* length_of_out_result, int n) {     auto classifier = reinterpret_cast<classifier*>(gethandle());      cv::mat img = cv::imread(img_path);     cv::imshow("img recieved c#", img);     std::vector<predictionresults> result = classifier->classify(std::string(img_path), n);     std::string str_info = "";     //...     *length_of_out_result = ss.str().length(); } here method accepts image(dll) : 
cdll2_api void classify_image(unsigned char* img_pointer, unsigned int height, unsigned int width,                                int step, char* out_result, int* length_of_out_result, int top_n_results)     {         auto classifier = reinterpret_cast<classifier*>(gethandle());         cv::mat img = cv::mat(height, width, cv_8uc3, (void*)img_pointer, step);         std::vector<prediction> result = classifier->classify(img, top_n_results);          //...         *length_of_out_result = ss.str().length();     } here code in c# application : dll import:  
[dllimport(@"cdll2.dll", callingconvention = callingconvention.cdecl, charset = charset.ansi)]         static extern void classify_image(intptr img, uint height, uint width, int step, byte[] out_result, out int out_result_length, int top_n_results = 2); the method sends image dll : 
private string classify_usingimage(bitmap img, int top_n_results) {     byte[] res = new byte[200];     int len;     bitmapdata bmpdata;     bmpdata = img.lockbits(new rectangle(0, 0, img.width, img.height), imagelockmode.readonly, img.pixelformat);     classify_image(bmpdata.scan0, (uint)bmpdata.height, (uint)bmpdata.width, bmpdata.stride, res, out len, top_n_results);     //remember unlock!!!     img.unlockbits(bmpdata);      string s = asciiencoding.ascii.getstring(res);     return s; } now, works when send image dll. if use imshow() show received image, image shown fine.   
the actual problem :
however, when resize same image , send using same method above, image distorted.
i need add that, if resize image using given c# method below, save it, , pass filename dll opened using classify(std::string(img_path), n); works perfectly.
here screenshot showing example of happening:
 image sent c# without being resized : 

 when same image first resized , sent dll: 
here image first resized (in c#), saved disk , filepath sent dll:  
this snippet responsible resizing (c#):  
/// <summary> /// resize image specified width , height. /// </summary> /// <param name="image">the image resize.</param> /// <param name="width">the width resize to.</param> /// <param name="height">the height resize to.</param> /// <returns>the resized image.</returns> public static bitmap resizeimage(image image, int width, int height) {     var destrect = new rectangle(0, 0, width, height);     var destimage = new bitmap(width, height);      destimage.setresolution(image.horizontalresolution, image.verticalresolution);      using (var graphics = graphics.fromimage(destimage))     {         graphics.compositingmode = compositingmode.sourcecopy;         graphics.compositingquality = compositingquality.highquality;         graphics.interpolationmode = interpolationmode.highqualitybicubic;         graphics.smoothingmode = smoothingmode.highquality;         graphics.pixeloffsetmode = pixeloffsetmode.highquality;          using (var wrapmode = new imageattributes())         {             wrapmode.setwrapmode(wrapmode.tileflipxy);             graphics.drawimage(image, destrect, 0, 0, image.width, image.height, graphicsunit.pixel, wrapmode);         }     }      return destimage; } and original image
this classify method uses filepath read images:    
std::vector<predictionresults> classifier::classify(const std::string & img_path, int n) {     cv::mat img = cv::imread(img_path);     cv::mat resizedimage;     std::vector<predictionresults> results;     std::vector<float> output;     // cv::imshow((std::string("img classify path") + type2str(img.type())), img);     if (isresizedenabled())     {         resizeimage(img, resizedimage);         output = predict(resizedimage);     }     else     {         output = predict(img);         img.release();     }      n = std::min<int>(labels_.size(), n);     std::vector<int> maxn = argmax(output, n);     (int = 0; < n; ++i)     {         int idx = maxn[i];         predictionresults r;         r.label = labels_[idx];         r.accuracy = output[idx];         results.push_back(r);     }      return results; } and resizeimage used in method above :   
void classifier::resizeimage(const cv::mat & source_image, cv::mat& resizedimage) {     size size(getresizeheight(), getresizeheight());     cv::resize(source_image, resizedimage, size);//resize image      check(!resizedimage.empty()) << "unable decode image "; } problem 2:
 distortion after resizing aside, facing discrepancy between resizing in c# , resizing using opencv itself.
 have created method using emgucv (also given below) , passed needed information , did not face such distortions happen when resize image in c# , send dll.
 however, discrepancy made me want understand causing these issues.
 here method uses emgucv.mat code works irrespective of resizing:   
private string classify_usingmat(string imgpath, int top_n_results) {     byte[] res = new byte[200];     int len;      emgu.cv.mat img = new emgu.cv.mat(imgpath, imreadmodes.color);      if (chkresizeimagecshap.checked)     {         cvinvoke.resize(img, img, new size(256, 256));     }      classify_image(img.datapointer, (uint)img.height, (uint)img.width, img.step, res, out len, top_n_results);      string s = asciiencoding.ascii.getstring(res);     return s; } why care?
 because, different accuracy when use opencv resize (both when use emgucv's cvinvoke.resize() , cv::resize()) resizing image in c#, saving disk , send image path opencv.
 either need fix distortion happening when deal images in c#, or need understand why resizing in opencv has different results c# resizing.  
so summarize issues , points made far :
- all situations intact, if resize image inside c# application, , pass info did before, image distorted (example given above)
- if resize image, save disk, , give filename opencvcreate newcv::mat, works without issues.
- if use emugcv, instead of workingbitmap, useemug.cv.mat, send needed parameters using mat object c#, no distortion happens. however, accuracy resized imagec#( see#2), different 1 resized image usingopencv. doesn't make difference if resize image before hand usingcvinvoke.resize()c#, , send resulting image dll, or send original image (usingemgucv) , resizing incppcode usingcv::resize(). prevents me usingemgucvor passing image original image , resizing insidedllusingopencv.
here images different results, showing issues :
--------------------no resizing------------------------------ 1.using bitmap-no resize, =>safe, acc=580295 2.using emgu.mat-no resize =>safe, acc=0.580262 3.using filepath-no resize, =>safe, acc=0.580262 --------------------resize in c#------------------------------ 4.using bitmap-csharp resize, =>unsafe, acc=0.770425 5.using emgu.mat-emguresize, =>unsafe, acc=758335 6.**using filepath-csharp resize, =>unsafe, acc=0.977649** --------------------resize in dll------------------------------ 7.using bitmap-dll resize, =>unsafe, acc=0.757484 8.using emgu.dll resize, =>unsafe, acc=0.758335 9.using filepath-dll resize, =>unsafe, acc=0.758335 i need accuracy @ #6. can see emgucv resize , opencv resize function used in dll, act similar , don't work expected(i.e. #2)!, c# resize method applied on image problematic, while if resized, saved , filename passed, result fine.      
you can see screen shots depicting different scenarios here : http://imgur.com/a/xbgiq
ok.thanks dear god , great helps @edchum, work.! did use imdecode @edchum suggested. how functions in dll , c# : 
#ifdef cdll2_exports #define cdll2_api __declspec(dllexport) #else #define cdll2_api __declspec(dllimport) #endif  #include "classification.h"  extern "c" {     cdll2_api void classify_image(unsigned char* img_pointer, long data_len, char* out_result, int* length_of_out_result, int top_n_results = 2); //... } the actual method :
cdll2_api void classify_image(unsigned char* img_pointer, long data_len,                               char* out_result, int* length_of_out_result, int top_n_results) {     auto classifier = reinterpret_cast<classifier*>(gethandle());     vector<unsigned char> inputimagebytes(img_pointer, img_pointer + data_len);     cv::mat img = imdecode(inputimagebytes, cv_load_image_color);      cv::imshow("img recieved c#", img);      std::vector<prediction> result = classifier->classify(img, top_n_results);     //...     *length_of_out_result = ss.str().length(); } here c# dll import:
[dllimport(@"cdll2.dll", callingconvention = callingconvention.cdecl, charset = charset.ansi)] static extern void classify_image(byte[] img, long data_len, byte[] out_result, out int out_result_length, int top_n_results = 2); and actual method sending image dll:
private string classify_usingimage(bitmap image, int top_n_results) {     byte[] result = new byte[200];     int len;     bitmap img;      if (chkresizeimagecshap.checked)         img = resizeimage(image, int.parse(txtwidth.text), (int.parse(txtheight.text)));     else         img = image;      //this situations, image not read disk, , stored in memort(e.g. image comes camera or snapshot)     imageformat fmt = new imageformat(image.rawformat.guid);     var imagecodecinfo = imagecodecinfo.getimageencoders().firstordefault(codec => codec.formatid == image.rawformat.guid);     if (imagecodecinfo == null)     {         fmt = imageformat.jpeg;     }      using (memorystream ms = new memorystream())     {         img.save(ms, fmt);         byte[] image_byte_array = ms.toarray();         classify_image(image_byte_array, ms.length, result, out len, top_n_results);     }      return asciiencoding.ascii.getstring(result); } by doing after resizing image c#, dont face distortions @ all. couldnt however, figure out why resize on opencv part wouldnt work expected!

Comments
Post a Comment