prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Alpha channel and grayscale in image-to-text with -image_channel_size=3
  For training image to text, the argument `-image_channel_size=3` imply that the images already have the good number of channel. However, some of my images are black and white and saved with only one channel or saved in RGB but with the alpha channel.
  I could fix it with a change in `onmt/inputters/image_dataset.py` [here](https://github.com/OpenNMT/OpenNMT-py/blob/master/onmt/inputters/image_dataset.py#L78):
  
  from this:
  ```
              if self.channel_size == 1:
                  img = transforms.ToTensor()(
                      Image.fromarray(cv2.imread(img_path, 0)))
              else:
                  img = transforms.ToTensor()(Image.open(img_path))
  ```
  to this:
  ```
              if self.channel_size == 1:
                  img = transforms.ToTensor()(
                      Image.fromarray(cv2.imread(img_path, 0)))
              else:
                  img = transforms.ToTensor()(
                      Image.fromarray(cv2.imread(img_path, 1)))
  ```
  The flag in `cv2.imread` with value of 1 tell cv2 to convert to RGB no matter what the original image is.
  
  Should I do a PR ?
  
  </issue>
  <code>
  [start of onmt/inputters/image_dataset.py]
  1 # -*- coding: utf-8 -*-
  2 
  3 import os
  4 
  5 import torch
  6 from torchtext.data import Field
  7 
  8 from onmt.inputters.datareader_base import DataReaderBase
  9 
  10 # domain specific dependencies
  11 try:
  12     from PIL import Image
  13     from torchvision import transforms
  14     import cv2
  15 except ImportError:
  16     Image, transforms, cv2 = None, None, None
  17 
  18 
  19 class ImageDataReader(DataReaderBase):
  20     """Read image data from disk.
  21 
  22     Args:
  23         truncate (tuple[int] or NoneType): maximum img size. Use
  24             ``(0,0)`` or ``None`` for unlimited.
  25         channel_size (int): Number of channels per image.
  26 
  27     Raises:
  28         onmt.inputters.datareader_base.MissingDependencyException: If
  29             importing any of ``PIL``, ``torchvision``, or ``cv2`` fail.
  30     """
  31 
  32     def __init__(self, truncate=None, channel_size=3):
  33         self._check_deps()
  34         self.truncate = truncate
  35         self.channel_size = channel_size
  36 
  37     @classmethod
  38     def from_opt(cls, opt):
  39         return cls(channel_size=opt.image_channel_size)
  40 
  41     @classmethod
  42     def _check_deps(cls):
  43         if any([Image is None, transforms is None, cv2 is None]):
  44             cls._raise_missing_dep(
  45                 "PIL", "torchvision", "cv2")
  46 
  47     def read(self, images, side, img_dir=None):
  48         """Read data into dicts.
  49 
  50         Args:
  51             images (str or Iterable[str]): Sequence of image paths or
  52                 path to file containing audio paths.
  53                 In either case, the filenames may be relative to ``src_dir``
  54                 (default behavior) or absolute.
  55             side (str): Prefix used in return dict. Usually
  56                 ``"src"`` or ``"tgt"``.
  57             img_dir (str): Location of source image files. See ``images``.
  58 
  59         Yields:
  60             a dictionary containing image data, path and index for each line.
  61         """
  62         if isinstance(images, str):
  63             images = DataReaderBase._read_file(images)
  64 
  65         for i, filename in enumerate(images):
  66             filename = filename.decode("utf-8").strip()
  67             img_path = os.path.join(img_dir, filename)
  68             if not os.path.exists(img_path):
  69                 img_path = filename
  70 
  71             assert os.path.exists(img_path), \
  72                 'img path %s not found' % filename
  73 
  74             if self.channel_size == 1:
  75                 img = transforms.ToTensor()(
  76                     Image.fromarray(cv2.imread(img_path, 0)))
  77             else:
  78                 img = transforms.ToTensor()(Image.open(img_path))
  79             if self.truncate and self.truncate != (0, 0):
  80                 if not (img.size(1) <= self.truncate[0]
  81                         and img.size(2) <= self.truncate[1]):
  82                     continue
  83             yield {side: img, side + '_path': filename, 'indices': i}
  84 
  85 
  86 def img_sort_key(ex):
  87     """Sort using the size of the image: (width, height)."""
  88     return ex.src.size(2), ex.src.size(1)
  89 
  90 
  91 def batch_img(data, vocab):
  92     """Pad and batch a sequence of images."""
  93     c = data[0].size(0)
  94     h = max([t.size(1) for t in data])
  95     w = max([t.size(2) for t in data])
  96     imgs = torch.zeros(len(data), c, h, w).fill_(1)
  97     for i, img in enumerate(data):
  98         imgs[i, :, 0:img.size(1), 0:img.size(2)] = img
  99     return imgs
  100 
  101 
  102 def image_fields(**kwargs):
  103     img = Field(
  104         use_vocab=False, dtype=torch.float,
  105         postprocessing=batch_img, sequential=False)
  106     return img
  107
  [end of onmt/inputters/image_dataset.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/onmt/inputters/image_dataset.py b/onmt/inputters/image_dataset.py
  --- a/onmt/inputters/image_dataset.py
  +++ b/onmt/inputters/image_dataset.py
  @@ -75,7 +75,8 @@
                   img = transforms.ToTensor()(
                       Image.fromarray(cv2.imread(img_path, 0)))
               else:
  -                img = transforms.ToTensor()(Image.open(img_path))
  +                img = Image.open(img_path).convert('RGB')
  +                img = transforms.ToTensor()(img)
               if self.truncate and self.truncate != (0, 0):
                   if not (img.size(1) <= self.truncate[0]
                           and img.size(2) <= self.truncate[1]):
  
verification_info: {"golden_diff": "diff --git a/onmt/inputters/image_dataset.py b/onmt/inputters/image_dataset.py\n--- a/onmt/inputters/image_dataset.py\n+++ b/onmt/inputters/image_dataset.py\n@@ -75,7 +75,8 @@\n                 img = transforms.ToTensor()(\n                     Image.fromarray(cv2.imread(img_path, 0)))\n             else:\n-                img = transforms.ToTensor()(Image.open(img_path))\n+                img = Image.open(img_path).convert('RGB')\n+                img = transforms.ToTensor()(img)\n             if self.truncate and self.truncate != (0, 0):\n                 if not (img.size(1) <= self.truncate[0]\n                         and img.size(2) <= self.truncate[1]):\n", "issue": "Alpha channel and grayscale in image-to-text with -image_channel_size=3\nFor training image to text, the argument `-image_channel_size=3` imply that the images already have the good number of channel. However, some of my images are black and white and saved with only one channel or saved in RGB but with the alpha channel.\r\nI could fix it with a change in `onmt/inputters/image_dataset.py` [here](https://github.com/OpenNMT/OpenNMT-py/blob/master/onmt/inputters/image_dataset.py#L78):\r\n\r\nfrom this:\r\n```\r\n            if self.channel_size == 1:\r\n                img = transforms.ToTensor()(\r\n                    Image.fromarray(cv2.imread(img_path, 0)))\r\n            else:\r\n                img = transforms.ToTensor()(Image.open(img_path))\r\n```\r\nto this:\r\n```\r\n            if self.channel_size == 1:\r\n                img = transforms.ToTensor()(\r\n                    Image.fromarray(cv2.imread(img_path, 0)))\r\n            else:\r\n                img = transforms.ToTensor()(\r\n                    Image.fromarray(cv2.imread(img_path, 1)))\r\n```\r\nThe flag in `cv2.imread` with value of 1 tell cv2 to convert to RGB no matter what the original image is.\r\n\r\nShould I do a PR ?\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\nimport os\n\nimport torch\nfrom torchtext.data import Field\n\nfrom onmt.inputters.datareader_base import DataReaderBase\n\n# domain specific dependencies\ntry:\n    from PIL import Image\n    from torchvision import transforms\n    import cv2\nexcept ImportError:\n    Image, transforms, cv2 = None, None, None\n\n\nclass ImageDataReader(DataReaderBase):\n    \"\"\"Read image data from disk.\n\n    Args:\n        truncate (tuple[int] or NoneType): maximum img size. Use\n            ``(0,0)`` or ``None`` for unlimited.\n        channel_size (int): Number of channels per image.\n\n    Raises:\n        onmt.inputters.datareader_base.MissingDependencyException: If\n            importing any of ``PIL``, ``torchvision``, or ``cv2`` fail.\n    \"\"\"\n\n    def __init__(self, truncate=None, channel_size=3):\n        self._check_deps()\n        self.truncate = truncate\n        self.channel_size = channel_size\n\n    @classmethod\n    def from_opt(cls, opt):\n        return cls(channel_size=opt.image_channel_size)\n\n    @classmethod\n    def _check_deps(cls):\n        if any([Image is None, transforms is None, cv2 is None]):\n            cls._raise_missing_dep(\n                \"PIL\", \"torchvision\", \"cv2\")\n\n    def read(self, images, side, img_dir=None):\n        \"\"\"Read data into dicts.\n\n        Args:\n            images (str or Iterable[str]): Sequence of image paths or\n                path to file containing audio paths.\n                In either case, the filenames may be relative to ``src_dir``\n                (default behavior) or absolute.\n            side (str): Prefix used in return dict. Usually\n                ``\"src\"`` or ``\"tgt\"``.\n            img_dir (str): Location of source image files. See ``images``.\n\n        Yields:\n            a dictionary containing image data, path and index for each line.\n        \"\"\"\n        if isinstance(images, str):\n            images = DataReaderBase._read_file(images)\n\n        for i, filename in enumerate(images):\n            filename = filename.decode(\"utf-8\").strip()\n            img_path = os.path.join(img_dir, filename)\n            if not os.path.exists(img_path):\n                img_path = filename\n\n            assert os.path.exists(img_path), \\\n                'img path %s not found' % filename\n\n            if self.channel_size == 1:\n                img = transforms.ToTensor()(\n                    Image.fromarray(cv2.imread(img_path, 0)))\n            else:\n                img = transforms.ToTensor()(Image.open(img_path))\n            if self.truncate and self.truncate != (0, 0):\n                if not (img.size(1) <= self.truncate[0]\n                        and img.size(2) <= self.truncate[1]):\n                    continue\n            yield {side: img, side + '_path': filename, 'indices': i}\n\n\ndef img_sort_key(ex):\n    \"\"\"Sort using the size of the image: (width, height).\"\"\"\n    return ex.src.size(2), ex.src.size(1)\n\n\ndef batch_img(data, vocab):\n    \"\"\"Pad and batch a sequence of images.\"\"\"\n    c = data[0].size(0)\n    h = max([t.size(1) for t in data])\n    w = max([t.size(2) for t in data])\n    imgs = torch.zeros(len(data), c, h, w).fill_(1)\n    for i, img in enumerate(data):\n        imgs[i, :, 0:img.size(1), 0:img.size(2)] = img\n    return imgs\n\n\ndef image_fields(**kwargs):\n    img = Field(\n        use_vocab=False, dtype=torch.float,\n        postprocessing=batch_img, sequential=False)\n    return img\n", "path": "onmt/inputters/image_dataset.py"}]}