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 :

enter image description here
when same image first resized , sent dll:

enter image description here

here image first resized (in c#), saved disk , filepath sent dll: enter image description here

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 :

  1. all situations intact, if resize image inside c# application, , pass info did before, image distorted (example given above)
  2. if resize image, save disk, , give filename opencv create new cv::mat, works without issues.
  3. if use emugcv , instead of working bitmap, use emug.cv.mat , send needed parameters using mat object c#, no distortion happens. however, accuracy resized image c#( see #2 ), different 1 resized image using opencv. doesn't make difference if resize image before hand using cvinvoke.resize() c#, , send resulting image dll, or send original image (using emgucv) , resizing in cpp code using cv::resize(). prevents me using emgucv or passing image original image , resizing inside dll using opencv.

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

Popular posts from this blog

Is there a better way to structure post methods in Class Based Views -

performance - Why is XCHG reg, reg a 3 micro-op instruction on modern Intel architectures? -

jquery - Responsive Navbar with Sub Navbar -