Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request to Add Support for YUV Format in visp_bridge #133

Open
m11112089 opened this issue Mar 26, 2024 · 0 comments
Open

Request to Add Support for YUV Format in visp_bridge #133

m11112089 opened this issue Mar 26, 2024 · 0 comments

Comments

@m11112089
Copy link

m11112089 commented Mar 26, 2024

Hello,

I encountered an issue when using usb_cam to launch my Logitech camera(C9xx) and converting the ROS image to ViSP format with visp_bridge. The converted image appears distorted.

This limitation is similar to the issue discussed in ros2/common_interfaces #76.

Upon reviewing the visp_bridge source code, I noticed it does not support the YUV format.

Could you consider adding support for this format in visp_bridge? I suggest incorporating the YUV422_YUY2 format specifically. This addition would align visp_bridge with the capabilities of sensor_msgs, the vpImageConvert Class, and usb_cam, all of which support the YUV422_YUY2 format.

Would it be acceptable for me to create a Pull Request to introduce this feature, or would you prefer to implement it differently?
Below is a proposed implementation snippet for handling YUV422_YUY2 format images in the toVispImageRGBa function:

vpImage<vpRGBa> toVispImageRGBa(const sensor_msgs::msg::Image &src)
{
  using sensor_msgs::image_encodings::BGR8;
  using sensor_msgs::image_encodings::BGRA8;
  using sensor_msgs::image_encodings::MONO8;
  using sensor_msgs::image_encodings::RGB8;
  using sensor_msgs::image_encodings::RGBA8;
  using sensor_msgs::image_encodings::YUV422_YUY2;

  vpImage<vpRGBa> dst(src.height, src.width);

  if (src.encoding == sensor_msgs::image_encodings::MONO8)
    for (unsigned i = 0; i < dst.getWidth(); ++i) {
      for (unsigned j = 0; j < dst.getHeight(); ++j) {

        dst[j][i] = vpRGBa(src.data[j * src.step + i], src.data[j * src.step + i], src.data[j * src.step + i]);
      }
    }
  else if (src.encoding == sensor_msgs::image_encodings::YUV422_YUY2) {
    int index = 0;
    unsigned char Y0, U, Y1, V;
    for (unsigned i = 0; i < src.width; i += 2) {
      for (unsigned j = 0; j < src.height; j++) {
        index = j * src.step + i * 2;
        Y0 = src.data[index];
        U = src.data[index + 1];
        Y1 = src.data[index + 2];
        V = src.data[index + 3];

        auto convertYUVtoRGB = [](unsigned char Y, unsigned char U, unsigned char V) -> vpRGBa {
          int C = Y - 16;
          int D = U - 128;
          int E = V - 128;
          unsigned char R = std::min(std::max((298 * C + 409 * E + 128) >> 8, 0), 255);
          unsigned char G = std::min(std::max((298 * C - 100 * D - 208 * E + 128) >> 8, 0), 255);
          unsigned char B = std::min(std::max((298 * C + 516 * D + 128) >> 8, 0), 255);
          return vpRGBa(R, G, B);
        };

        dst[j][i] = convertYUVtoRGB(Y0, U, V);
        if (i + 1 < src.width) { // Make sure not to exceed the image width
          dst[j][i + 1] = convertYUVtoRGB(Y1, U, V);
        }
      }
    }
  } else {
    unsigned nc = sensor_msgs::image_encodings::numChannels(src.encoding);

    for (unsigned i = 0; i < dst.getWidth(); ++i) {
      for (unsigned j = 0; j < dst.getHeight(); ++j) {
        dst[j][i] = vpRGBa(src.data[j * src.step + i * nc + 0], src.data[j * src.step + i * nc + 1],
                           src.data[j * src.step + i * nc + 2]);
      }
    }
  }
  return dst;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant