简体   繁体   中英

Error when converting from HSV to BGR, or HSV to JPEG in openCV after using inRange

I am using openCV 3.1.0 (I have tried with 2.4.9, with same problem). I want to output a HSV mat to jpeg:

// .. Getting JPEG content into memory
// JPEG to mat
Mat imgBuf=Mat(1, jpegContent, CV_8UC3, jpegSize);
Mat imgMat=imdecode(imgBuf, CV_LOAD_IMAGE_COLOR);
free(jpegContent);
if(imgMat.data == NULL) {
    // Some error handling
}
// Now the JPEG is decoded and reside in imgMat
cvtColor(imgMat, imgMat, CV_BGR2HSV); // Converting to HSV
Mat tmp;
inRange(imgMat, Scalar(0, 0, 0), Scalar(8, 8, 8), tmp); // Problem goes here
cvtColor(tmp, imgMat, CV_HSV2BGR);
// Mat to JPEG
vector<uchar> buf;
imencode(".jpg", imgMat, buf, std::vector<int>());
outputJPEG=(unsigned char*)malloc(buf.size());
memcpy(outputJPEG, &buf[0], buf.size());
// ... Output JPEG

The problem is, when i do cvtColor(tmp, imgMat, CV_HSV2BGR) with inRange , my program will fail with:

OpenCV Error: Assertion failed (scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F)) in cvtColor, file /home/pi/opencv/src/opencv-3.1.0/modules/imgproc/src/color.cpp, line 8176

terminate called after throwing an instance of 'cv::Exception' what(): /home/pi/opencv/src/opencv-3.1.0/modules/imgproc/src/color.cpp:8176: error: (-215) scn == 3 && (dcn == 3 || dcn == 4) && (depth == CV_8U || depth == CV_32F) in function cvtColor

If i removed inRange , the program work just fine. I have tried to remove the cvtColor call, letting imencode to do its job, automatically converting HSV to BGR then to JPEG. This time, no more assertion failed, but i got corrupted JPEG image, as GStreamer complains:

gstrtpjpegpay.c(581): gst_rtp_jpeg_pay_read_sof (): /GstPipeline:pipeline0/GstRtpJPEGPay:rtpjpegpay0 WARNING: from element /GstPipeline:pipeline0/GstRtpJPEGPay:rtpjpegpay0: Wrong SOF length 11.

Again, removing inRange also solves this issue, it produces good JPEG data.

So, is that i am invoking inRange improperly that cause corrupted image data? If yes, what is the correct way to use inRange ?

inRange produces a single channel binary matrix, ie a CV_8UC1 matrix with values either 0 or 255 .

So you cannot convert tmp with HSV2BGR , because the source image tmp doesn't have 3 channels.

OpenCV is telling you exactly this: scn (source channels) is not 3.


Since you probably want to keep and then convert to BGR only part of the image in your range, you can:

  1. set to black everything outside the range: imgMat.setTo(Scalar(0,0,0), ~tmp);
  2. convert the resulting image to BGR: cvtColor(imgMat, imgMat, CV_HSV2BGR);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM