Explorar el Código

Added a tool to adjust image brightness and contrast. Useful for dark images (#494)

* Added a tool to adjust image brightness and contrast. Useful for dark images.

* Refactor brightness and contrast adjuster

* Fix syntax error in Python2

Co-authored-by: Kentaro Wada <www.kentaro.wada@gmail.com>
alexander-g hace 4 años
padre
commit
d986e8fc08

+ 20 - 0
labelme/app.py

@@ -22,6 +22,7 @@ from labelme.label_file import LabelFile
 from labelme.label_file import LabelFileError
 from labelme.logger import logger
 from labelme.shape import Shape
+from labelme.widgets import BrightnessContrastDialog
 from labelme.widgets import Canvas
 from labelme.widgets import LabelDialog
 from labelme.widgets import LabelListWidget
@@ -401,6 +402,11 @@ class MainWindow(QtWidgets.QMainWindow):
                           shortcuts['fit_width'], 'fit-width',
                           self.tr('Zoom follows window width'),
                           checkable=True, enabled=False)
+        brightnessContrast = action('&Brightness Contrast',
+                                    self.brightnessContrast,
+                                    None, 'color',
+                                    'Adjust brightness and contrast',
+                                    enabled=False)
         # Group zoom controls into a list for easier toggling.
         zoomActions = (self.zoomWidget, zoomIn, zoomOut, zoomOrg,
                        fitWindow, fitWidth)
@@ -455,6 +461,7 @@ class MainWindow(QtWidgets.QMainWindow):
             createLineStripMode=createLineStripMode,
             zoom=zoom, zoomIn=zoomIn, zoomOut=zoomOut, zoomOrg=zoomOrg,
             fitWindow=fitWindow, fitWidth=fitWidth,
+            brightnessContrast=brightnessContrast,
             zoomActions=zoomActions,
             openNextImg=openNextImg, openPrevImg=openPrevImg,
             fileMenuActions=(open_, opendir, save, saveAs, close, quit),
@@ -498,6 +505,7 @@ class MainWindow(QtWidgets.QMainWindow):
                 createPointMode,
                 createLineStripMode,
                 editMode,
+                brightnessContrast,
             ),
             onShapesPresent=(saveAs, hideAll, showAll),
         )
@@ -554,6 +562,7 @@ class MainWindow(QtWidgets.QMainWindow):
                 fitWindow,
                 fitWidth,
                 None,
+                brightnessContrast,
             ),
         )
 
@@ -584,6 +593,7 @@ class MainWindow(QtWidgets.QMainWindow):
             copy,
             delete,
             undo,
+            brightnessContrast,
             None,
             zoomIn,
             zoom,
@@ -1238,6 +1248,16 @@ class MainWindow(QtWidgets.QMainWindow):
         self.zoomMode = self.FIT_WIDTH if value else self.MANUAL_ZOOM
         self.adjustScale()
 
+    def brightnessContrast(self, value):
+
+        def onNewBrightnessContrast(qimage):
+            self.canvas.loadPixmap(QtGui.QPixmap.fromImage(qimage),
+                                   clear_shapes=False)
+
+        dialog = BrightnessContrastDialog(
+            self.filename, onNewBrightnessContrast, parent=self)
+        dialog.exec_()
+
     def togglePolygons(self, value):
         for item in self.labelList:
             item.setCheckState(Qt.Checked if value else Qt.Unchecked)

+ 2 - 0
labelme/widgets/__init__.py

@@ -1,5 +1,7 @@
 # flake8: noqa
 
+from .brightness_contrast_dialog import BrightnessContrastDialog
+
 from .canvas import Canvas
 
 from .color_dialog import ColorDialog

+ 45 - 0
labelme/widgets/brightness_contrast_dialog.py

@@ -0,0 +1,45 @@
+from qtpy.QtCore import Qt
+from qtpy import QtGui
+from qtpy import QtWidgets
+
+from PIL import Image
+from PIL import ImageEnhance
+
+
+class BrightnessContrastDialog(QtWidgets.QDialog):
+    def __init__(self, filename, callback, parent=None):
+        super(BrightnessContrastDialog, self).__init__(parent)
+        self.setModal(True)
+        self.setWindowTitle('Brightness/Contrast')
+
+        self.slider_brightness = self._create_slider()
+        self.slider_contrast = self._create_slider()
+
+        formLayout = QtWidgets.QFormLayout()
+        formLayout.addRow(self.tr('Brightness'), self.slider_brightness)
+        formLayout.addRow(self.tr('Contrast'), self.slider_contrast)
+        self.setLayout(formLayout)
+
+        self.img = Image.open(filename).convert('RGBA')
+        self.callback = callback
+
+    def onNewValue(self, value):
+        brightness = self.slider_brightness.value() / 100.
+        contrast = self.slider_contrast.value() / 100.
+
+        img = self.img
+        img = ImageEnhance.Brightness(img).enhance(brightness)
+        img = ImageEnhance.Contrast(img).enhance(contrast)
+
+        bytes = img.tobytes('raw', 'RGBA')
+        qimage = QtGui.QImage(bytes,
+                              img.size[0], img.size[1],
+                              QtGui.QImage.Format_RGB32).rgbSwapped()
+        self.callback(qimage)
+
+    def _create_slider(self):
+        slider = QtWidgets.QSlider(Qt.Horizontal)
+        slider.setRange(0, 300)
+        slider.setValue(100)
+        slider.valueChanged.connect(self.onNewValue)
+        return slider

+ 3 - 2
labelme/widgets/canvas.py

@@ -708,9 +708,10 @@ class Canvas(QtWidgets.QWidget):
             self.drawingPolygon.emit(False)
         self.repaint()
 
-    def loadPixmap(self, pixmap):
+    def loadPixmap(self, pixmap, clear_shapes=True):
         self.pixmap = pixmap
-        self.shapes = []
+        if clear_shapes:
+            self.shapes = []
         self.repaint()
 
     def loadShapes(self, shapes, replace=True):