def qimage2numpy(qimage: QImage): """Convert QImage to numpy.ndarray. The dtype defaults to uint8 for QImage.Format_Indexed8 or `bgra_dtype` (i.e. a record array) for 32bit color images. You can pass a different dtype to use, or 'array' to get a 3D uint8 array for color images.""" result_shape = (qimage.height(), qimage.width()) temp_shape = (qimage.height(), int(qimage.bytesPerLine() * 8 / qimage.depth())) if qimage.format() in (QImage.Format_ARGB32_Premultiplied, QImage.Format_ARGB32, QImage.Format_RGB32): dtype = np.uint8 result_shape += (4,) temp_shape += (4,) elif qimage.format() == QtGui.QImage.Format_Indexed8: dtype = np.uint8 else: raise ValueError("qimage2numpy only supports 32bit and 8bit images") # FIXME: raise error if alignment does not match buf = qimage.bits().asstring(qimage.byteCount()) result = np.frombuffer(buf, dtype).reshape(temp_shape) if result_shape != temp_shape: result = result[:, :result_shape[1]] if qimage.format() == QImage.Format_RGB32 and dtype == np.uint8: result = result[..., :3] return result
def white_outline(image: QImage, sigma=6, repeat=6) -> QImage: if image.format() != QImage.Format_ARGB32: image = image.convertToFormat(QImage.Format_ARGB32) bits = image.bits() bits.setsize(image.byteCount()) shape = (image.width() * image.height()) strides = (4,) alpha = numpy.ndarray(shape=shape, dtype=numpy.uint8, buffer=bits, strides=strides, offset=3) color = numpy.ndarray(shape=shape, dtype=numpy.uint8) color.fill(255) alpha = alpha.reshape((image.width(), image.height())) alpha = alpha.astype(numpy.float) alpha = gaussian_filter(alpha, sigma=sigma) alpha *= repeat numpy.clip(alpha, 0, 255, out=alpha) alpha = alpha.astype(numpy.uint8) alpha = alpha.reshape(shape) arr = numpy.dstack((color, color, color, alpha)) return QImage(arr, image.width(), image.height(), QImage.Format_ARGB32)
def qimageview(image: QImage) -> ndarray: if not isinstance(image, QtGui.QImage): raise TypeError("image argument must be a QImage instance") shape = image.height(), image.width(), 4 strides0 = image.bytesPerLine() format = image.format() dtype = "|u1" strides1 = 4 strides2 = 1 if format == QtGui.QImage.Format_Invalid: raise ValueError("qimageview got invalid QImage") image.__array_interface__ = { 'shape': shape, 'typestr': dtype, 'data': getdata(image), 'strides': (strides0, strides1, strides2), 'version': 3, } result = np.asarray(image) result[..., :3] = result[..., 2::-1] del image.__array_interface__ return result
def add_transparency(qimage: QImage) -> QImage: """ Add transparent window borders according to Ubuntu 19.10 titlebar style :param qimage: image with non transparent top left and right corners :return: image with transparent top left and right corners """ if not qimage.hasAlphaChannel(): assert qimage.format() == QImage.Format_RGB32 transparent = QImage(qimage.size(), QImage.Format_ARGB32_Premultiplied) transparent.fill(Qt.black) painter = QPainter() painter.begin(transparent) painter.drawImage(0, 0, qimage) painter.end() qimage = transparent image_width = qimage.width() y = -1 for width in (5, 3, 2, 1): y += 1 for x in range(width): color = qimage.pixelColor(x, y) color.setAlpha(0) qimage.setPixelColor(x, y, color) qimage.setPixelColor(image_width - x - 1, y, color) return qimage
def update(self, model): img_fname = model.getImageName() if img_fname is None: return arImgList = model.getARImageInfo() image = QImage(img_fname) painter = QPainter() if image.format() != QImage.Format(3): painter.begin(image) for imInfo in arImgList: if imInfo['show']: overlay = QImage(imInfo['fname']) painter.drawImage(image.width() / 2 + imInfo['loc_x'], image.height() / 2 + imInfo['loc_y'], overlay) painter.end() # label = QLabel() self.pic.setPixmap(QPixmap.fromImage(image)) # label.show() # progress bar if PBAR_ENABLE: start = model.lastSignLocation stop = start + model.lastDistanceToNext self.pbar.setRange(100 * start, 100 * stop) self.pbar.setValue(100 * (stop - model.nextSignal.distanceTo))
def _scale_image( settings: Dict, source_image: QImage ): source_image_width = source_image.width() source_image_height = source_image.height() source_image_ratio = source_image_height / source_image_width pixel_box_size = settings[ 'pixel_box_size' ] plate_width = settings[ 'plate_width' ] plate_height = settings[ 'plate_height' ] result_image_width = int( plate_width / pixel_box_size ) result_image_height = int( plate_height / pixel_box_size ) result_image_ratio = result_image_height / result_image_width result = QImage( result_image_width, result_image_height, source_image.format() ) if source_image_ratio < result_image_ratio: scaled_image = source_image.scaledToWidth( result_image_width ) position = QPoint( 0, result_image_height / 2 - scaled_image.height() / 2 ) else: scaled_image = source_image.scaledToHeight( result_image_height ) position = QPoint( result_image_width / 2 - scaled_image.width() / 2, 0 ) result.fill( Qt.white ) painter = QPainter( result ) painter.drawImage( position, scaled_image ) painter.end() return result
def set_source_img(self, img: QImage): self.source_img_format = img.format() self.source_complex_mat = [] # get the grey value a = 0 for w in range(img.width()): temp = [] for h in range(img.height()): value = QColor(img.pixel(w, h)) grey = value.red() * 0.299 + value.green( ) * 0.587 + value.blue() * 0.144 grey *= pow(-1, w + h) # move to middle temp.append(int(grey)) self.source_complex_mat.append(temp)
def format_image(self, raw_image: QImage): masked = self._mask.mask(raw_image) image_size = masked.size() content_size = image_size * self._scale_factor image = QImage(image_size, raw_image.format()) image.fill(_white) painter = QPainter(image) def get_image_content_rect(): x = (image_size.width() - content_size.width()) / 2 y = (image_size.height() - content_size.height()) / 2 return QRect(QPoint(x, y), content_size) painter.drawImage(get_image_content_rect(), masked.scaled(content_size)) painter.end() return image
def add_filmstrip(thumbnail: QImage) -> QImage: """ Overlays a filmstrip onto the thumbnail. Keeps the thumbnail's dimensions the same. :param thumbnail: thumbnail on which to put the filmstrip :return a copy of the thumbnail """ format = thumbnail.format() filmstrip = QImage(xpm_data) filmstrip_width = filmstrip.width() filmstrip_height = filmstrip.height() filmstrip_right = filmstrip.mirrored(horizontal=True, vertical=False) thumbnail_right_col = thumbnail.width() - filmstrip_width painter = QPainter(thumbnail) # add filmstrips to left and right for i in range(thumbnail.height() // filmstrip_height): painter.drawImage(0, i * filmstrip_height, filmstrip) painter.drawImage(thumbnail_right_col, i * filmstrip_height, filmstrip_right) # now do the remainder, at the bottom remaining_height = thumbnail.height() % filmstrip_height if remaining_height: painter.drawImage( 0, thumbnail.height() - remaining_height, filmstrip.copy(0, 0, filmstrip_width, remaining_height), ) painter.drawImage( thumbnail_right_col, thumbnail.height() - remaining_height, filmstrip_right.copy(0, 0, filmstrip_width, remaining_height), ) return thumbnail
def handle_open_for_json(self): json_obj = self.parse_json() for file_name in list(set(json_obj['open-windows'])): if os.path.isfile(file_name): image = QImage(file_name) if not image.isNull(): self.container.lwindow.add_list_item(file_name) self.container.bwindow.update_image_info(file_name) # Create a new image window with the option 0 if image.format() == QImage.Format_Indexed8: # Create a gray scale image subwindow = GrayscaleImageWindow(file_name, 0, self.container) else: # Create a rgb color image subwindow = RgbImageWindow(file_name, 0, self.container) if not subwindow: QMessageBox.information(self.container, "Error", "Fail to create a sub window") else: self.container.mdiArea.addSubWindow(subwindow) subwindow.show()
def drop_shadow(image: QImage) -> QImage: if image.format() != QImage.Format_ARGB32: image = image.convertToFormat(QImage.Format_ARGB32) bits = image.bits() bits.setsize(image.byteCount()) shape = (image.width() * image.height()) strides = (4,) alpha = numpy.ndarray(shape=shape, dtype=numpy.uint8, buffer=bits, strides=strides, offset=3) color = numpy.ndarray(shape=shape, dtype=numpy.uint8) color.fill(0) alpha = alpha.reshape((image.width(), image.height())) alpha = gaussian_filter(alpha, sigma=10) alpha = alpha.reshape(shape) arr = numpy.dstack((color, color, color, alpha)) return QImage(arr, image.width(), image.height(), QImage.Format_ARGB32)
def apply_groups(self, pixmap: QPixmap, *groups: ManipulationGroup) -> QPixmap: """Manipulate pixmap according all manipulations in groups. Args: pixmap: The QPixmap to manipulate. groups: Manipulation groups containing all manipulations to apply in series. Returns: The manipulated pixmap. """ _logger.debug("Manipulate: applying %d groups", len(groups)) # Convert original pixmap to python bytes image = pixmap.toImage() bits = image.constBits() bits.setsize(image.byteCount()) data = bits.asstring() # Apply changes on the byte-level for group in groups: data = self._apply_group(group, data) # Convert updated bytes back to pixmap image = QImage( data, image.width(), image.height(), image.bytesPerLine(), image.format() ) return QPixmap(image)
def run_facedetect(filename: str) -> Tuple[QImage, List[Any]]: image = QImage(filename) if image.format() != QImage.Format_RGB32: image = image.convertToFormat(QImage.Format_RGB32) image = image.scaled(image.width() * scale_factor, image.height() * scale_factor, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) bits = image.bits() bits.setsize(image.byteCount()) array = numpy.ndarray(shape=(image.height(), image.bytesPerLine() // 4, 4), dtype=numpy.uint8, buffer=bits) array = array[:image.height(), :image.width(), :3] img = cv2.imread(filename, cv2.IMREAD_COLOR) print(img.shape) print(array.shape) print(img) print() print(array) detector = dlib.get_frontal_face_detector() results = detector(img) print(results) results = detector(array) print(results) print("detected {} faces".format(len(results))) image = image.scaled(image.width() // scale_factor, image.height() // scale_factor) return image, results
def handle_open(self, relative_path: str = ""): if not relative_path: my_path = "/Users/Carlistle/Developer/PyCharmWorkspace/CuteImage/Photos_Library_photoslibrary/" else: my_path = "/Users/Carlistle/Developer/PyCharmWorkspace/CuteImage/Photos_Library_photoslibrary/" + relative_path file_name = QFileDialog.getOpenFileName(self.container, "Choose an image file", my_path) if os.path.isfile(file_name[0]): image = QImage(file_name[0]) if not image.isNull(): self.container.lwindow.add_list_item(file_name[0]) self.container.bwindow.update_image_info(file_name[0]) # Create a new image window with the option 0 if image.format() == QImage.Format_Indexed8: # Create a gray scale image subwindow = GrayscaleImageWindow(file_name[0], 0, self.container) else: # Create a rgb color image subwindow = RgbImageWindow(file_name[0], 0, self.container) if not subwindow: QMessageBox.information(self.container, "Error", "Fail to create a sub window") else: self.container.mdiArea.addSubWindow(subwindow) subwindow.show()
def run_api(): # pdf = Poppler.Document() # page = Poppler.Page() pdf = 0 page = 0 image = QImage() byte_data = QByteArray() color_theme = 'light' #allowed color themes: 'light','dark','sepia' while True: s = input() tokens = s.split(' ') if tokens[0] == 'open': #open a pdf file pdf = Poppler.Document.load(tokens[1]) pdf.setRenderHint(Poppler.Document.TextAntialiasing) if tokens[0] == 'page': #open a page of the current pdf page = pdf.page(tokens[1]) if tokens[0] == 'pages': #returns number of pages print(pdf.numPages()) if tokens[0] == 'color': #set color theme color_theme = tokens[1] if tokens[0] == 'textlist': #outputs textlist as a json file textlist = page.textList() textlist_json = [] for text in textlist: bb = text.boundingBox() d = {'text': text.text(), 'x': bb.x(), 'y': bb.y(), 'width': bb.width(), 'height': bb.height()} textlist_json.append(d) print(json.dumps(textlist_json)) if tokens[0] == 'render': #output pixel data to stdout image = page.renderToImage(3 * 72, 3 * 72, -1, -1, -1, -1) print(image.format()) if color_theme == 'dark': for x in range(image.width()): for y in range(image.height()): rgb = image.pixelColor(x, y) rgb.setRed(int(linear_interpolation(234, 68, rgb.red() / 255))) rgb.setGreen(int(linear_interpolation(234, 68, rgb.green() / 255))) rgb.setBlue(int(linear_interpolation(234, 68, rgb.blue() / 255))) image.setPixelColor(x, y, rgb) # print(image.data) # bits = image.bits() # byte_data.fromRawData(image.data) # print(byte_data) ba = QByteArray() buffer = QBuffer(ba) buffer.open(QIODevice.WriteOnly) image.save(buffer, "PNG") # writes image into ba in PNG format ba2 = buffer.data() for i in ba. bits = image.constBits() bits.setsize(image.width() * image.height() * 4) print(str(bits)) print(dir(bits)) print(bits.asarray()) print(str(bits.asarray())) imgPtr = c_void_p(bits.__int__()) print(dir(imgPtr)) # for i in range(len(bits)): # print(bits[i]) # print(image.constBits()[0]) # print(bits) # print(type(bits)) # for i in range(image.width()): # for j in range(image.height()): # # print(image.pixel(i, j)) # print(bits[i]) # # color = QColor(image.pixel(i,j)) # # print(image.pixel(i,j).red(), image.pixel(i,j).green(), image.pixel(i,j).blue()) if tokens[0] == 'toc': toc = pdf.toc()
def get_diff(self, image: QImage, ref_image: QImage) -> QImage: """ Get a difference image that represents the differences between two images. Identical pixels produce a black pixel, otherwise the pixel is the absolute difference of the two colors. If the images are different sizes, a diff image will be returned regardless of the tolerances specified at construction time. In that case, the areas that do not overlap will have the pixels from the image that has pixels in those areas. In an area where neither image has pixels (because they have different widths AND heights), the color will be white. """ diff_width = max(ref_image.width(), image.width()) diff_height = max(ref_image.height(), image.height()) diff_image = QImage(diff_width, diff_height, ref_image.format()) diff_rms = 0 num_diffs = 0 self.max_pix_diff = 0 total_num_pixels = 0 for i in range(diff_width): for j in range(diff_height): actual_valid_coord = image.valid(i, j) ref_valid_coord = ref_image.valid(i, j) if actual_valid_coord and ref_valid_coord: pixel = image.pixelColor(i, j) ref_pixel = ref_image.pixelColor(i, j) total_num_pixels += 1 if pixel == ref_pixel: diff_image.setPixelColor(i, j, self.PIXEL_COLOR_NO_DIFF) else: num_diffs += 1 diff_rms_pix, diff_color = self._get_pixel_diff(pixel, ref_pixel) diff_rms += diff_rms_pix max_diff = max(diff_color) if max_diff > self.max_pix_diff: self.max_pix_diff = max_diff diff_image.setPixelColor(i, j, QColor(*diff_color)) elif actual_valid_coord: pixel = image.pixelColor(i, j) diff_image.setPixelColor(i, j, pixel) elif ref_valid_coord: ref_pixel = ref_image.pixelColor(i, j) diff_image.setPixelColor(i, j, ref_pixel) else: diff_image.setPixelColor(i, j, self.PIXEL_COLOR_NO_PIXEL) self.num_diffs_perc = (num_diffs / total_num_pixels) * 100 if num_diffs == 0: self.diff_rms_perc = 0.0 if ref_image.width() == image.width() and ref_image.height() == image.height(): return None return diff_image else: diff_rms /= num_diffs self.diff_rms_perc = diff_rms * 100 rms_ok = (self.rms_tol_perc is None or self.diff_rms_perc <= self.rms_tol_perc) num_diff_ok = (self.num_tol_perc is None or self.num_diffs_perc <= self.num_tol_perc) max_pix_diff_ok = (self.max_pix_diff_tol is None or self.max_pix_diff <= self.max_pix_diff_tol) diff_acceptable = (rms_ok and num_diff_ok and max_pix_diff_ok) return None if diff_acceptable else diff_image
class imageLabel(QLabel): """Subclass of QLabel for displaying image""" def __init__(self, parent, image=None): super().__init__(parent) self.parent = parent self.image = QImage() #self.image = "images/parrot.png" #self.original_image = self.image.copy self.original_image = self.image self.rubber_band = QRubberBand(QRubberBand.Rectangle, self) # setBackgroundRole() will create a bg for the image #self.setBackgroundRole(QPalette.Base) self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) self.setScaledContents(True) # Load image self.setPixmap(QPixmap().fromImage(self.image)) self.setAlignment(Qt.AlignCenter) def openImage(self): """Load a new image into the """ image_file, _ = QFileDialog.getOpenFileName( self, "Open Image", "", "PNG Files (*.png);;JPG Files (*.jpeg *.jpg );;Bitmap Files (*.bmp);;\ GIF Files (*.gif)") if image_file: # Reset values when opening an image self.parent.zoom_factor = 1 #self.parent.scroll_area.setVisible(True) self.parent.print_act.setEnabled(True) self.parent.updateActions() # Reset all sliders self.parent.brightness_slider.setValue(0) # Get image format image_format = self.image.format() self.image = QImage(image_file) self.original_image = self.image.copy() #pixmap = QPixmap(image_file) self.setPixmap(QPixmap().fromImage(self.image)) #image_size = self.image_label.sizeHint() self.resize(self.pixmap().size()) #self.scroll_area.setMinimumSize(image_size) #self.image_label.setPixmap(pixmap.scaled(self.image_label.size(), # Qt.KeepAspectRatio, Qt.SmoothTransformation)) elif image_file == "": # User selected Cancel pass else: QMessageBox.information(self, "Error", "Unable to open image.", QMessageBox.Ok) def saveImage(self): """Save the image displayed in the label.""" #TODO: Add different functionality for the way in which the user can save their image. if self.image.isNull() == False: image_file, _ = QFileDialog.getSaveFileName( self, "Save Image", "", "PNG Files (*.png);;JPG Files (*.jpeg *.jpg );;Bitmap Files (*.bmp);;\ GIF Files (*.gif)") if image_file and self.image.isNull() == False: self.image.save(image_file) else: QMessageBox.information(self, "Error", "Unable to save image.", QMessageBox.Ok) else: QMessageBox.information(self, "Empty Image", "There is no image to save.", QMessageBox.Ok) def clearImage(self): """ """ #TODO: If image is not null ask to save image first. pass def revertToOriginal(self): """Revert the image back to original image.""" #TODO: Display message dialohg to confirm actions self.image = self.original_image self.setPixmap(QPixmap().fromImage(self.image)) self.repaint() #self.parent.zoom_factor = 1 def resizeImage(self): """Resize image.""" #TODO: Resize image by specified size if self.image.isNull() == False: resize = QTransform().scale(0.5, 0.5) pixmap = QPixmap(self.image) resized_image = pixmap.transformed(resize, mode=Qt.SmoothTransformation) #rotated = pixmap.trueMatrix(transform90, pixmap.width, pixmap.height) #self.image_label.setPixmap(rotated) #self.image_label.setPixmap(rotated.scaled(self.image_label.size(), # Qt.KeepAspectRatio, Qt.SmoothTransformation)) self.image = QImage(resized_image) self.setPixmap(resized_image) #self.image = QPixmap(rotated) self.setScaledContents(True) self.repaint() # repaint the child widget else: # No image to rotate pass def cropImage(self): """Crop selected portions in the image.""" if self.image.isNull() == False: rect = QRect(10, 20, 400, 200) original_image = self.image cropped = original_image.copy(rect) self.image = QImage(cropped) self.setPixmap(QPixmap().fromImage(cropped)) def rotateImage90(self, direction): """Rotate image 90º clockwise or counterclockwise.""" if self.image.isNull() == False: if direction == "cw": transform90 = QTransform().rotate(90) elif direction == "ccw": transform90 = QTransform().rotate(-90) pixmap = QPixmap(self.image) #TODO: Try flipping the height/width when flipping the image rotated = pixmap.transformed(transform90, mode=Qt.SmoothTransformation) self.resize(self.image.height(), self.image.width()) #rotated = pixmap.trueMatrix(transform90, pixmap.width, pixmap.height) #self.image_label.setPixmap(rotated.scaled(self.image_label.size(), # Qt.KeepAspectRatio, Qt.SmoothTransformation)) self.image = QImage(rotated) #self.setPixmap(rotated) self.setPixmap( rotated.scaled(self.size(), Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation)) self.repaint() # repaint the child widget else: # No image to rotate pass def flipImage(self, axis): """ Mirror the image across the horizontal axis. """ if self.image.isNull() == False: if axis == "horizontal": flip_h = QTransform().scale(-1, 1) pixmap = QPixmap(self.image) flipped = pixmap.transformed(flip_h) elif axis == "vertical": flip_v = QTransform().scale(1, -1) pixmap = QPixmap(self.image) flipped = pixmap.transformed(flip_v) #self.image_label.setPixmap(flipped) #self.image_label.setPixmap(flipped.scaled(self.image_label.size(), # Qt.KeepAspectRatio, Qt.SmoothTransformation)) self.image = QImage(flipped) self.setPixmap(flipped) #self.image = QPixmap(flipped) self.repaint() else: # No image to flip pass def convertToGray(self): """Convert image to grayscale.""" if self.image.isNull() == False: converted_img = self.image.convertToFormat( QImage.Format_Grayscale16) #self.image = converted_img self.image = QImage(converted_img) self.setPixmap(QPixmap().fromImage(converted_img)) self.repaint() def convertToRGB(self): """Convert image to RGB format.""" if self.image.isNull() == False: converted_img = self.image.convertToFormat(QImage.Format_RGB32) #self.image = converted_img self.image = QImage(converted_img) self.setPixmap(QPixmap().fromImage(converted_img)) self.repaint() def convertToSepia(self): """Convert image to sepia filter.""" #TODO: Sepia #704214 rgb(112, 66, 20) #TODO: optimize speed that the image converts, or add to thread if self.image.isNull() == False: for row_pixel in range(self.image.width()): for col_pixel in range(self.image.height()): current_val = QColor(self.image.pixel( row_pixel, col_pixel)) # Calculate r, g, b values for current pixel red = current_val.red() green = current_val.green() blue = current_val.blue() new_red = int(0.393 * red + 0.769 * green + 0.189 * blue) new_green = int(0.349 * red + 0.686 * green + 0.168 * blue) new_blue = int(0.272 * red + 0.534 * green + 0.131 * blue) # Set the new RGB values for the current pixel if new_red > 255: red = 255 else: red = new_red if new_green > 255: green = 255 else: green = new_green if new_blue > 255: blue = 255 else: blue = new_blue new_value = qRgb(red, green, blue) self.image.setPixel(row_pixel, col_pixel, new_value) self.setPixmap(QPixmap().fromImage(self.image)) self.repaint() def changeBrighteness(self, value): #TODO: Reset the value of brightness, remember the original values # as going back to 0, i.e. keep track of original image's values #TODO: modify values based on original image if (value < -255 | value > 255): return self.image for row_pixel in range(self.image.width()): for col_pixel in range(self.image.height()): current_val = QColor(self.image.pixel(row_pixel, col_pixel)) red = current_val.red() green = current_val.green() blue = current_val.blue() new_red = red + value new_green = green + value new_blue = blue + value # Set the new RGB values for the current pixel if new_red > 255: red = 255 elif new_red < 0: red = 0 else: red = new_red if new_green > 255: green = 255 elif new_green < 0: green = 0 else: green = new_green if new_blue > 255: blue = 255 elif new_blue < 0: blue = 0 else: blue = new_blue new_value = qRgb(red, green, blue) self.image.setPixel(row_pixel, col_pixel, new_value) self.setPixmap(QPixmap().fromImage(self.image)) def changeContrast(self, contrast): """Change the contrast of the pixels in the image. Contrast is the difference between max and min pixel intensity.""" for row_pixel in range(self.image.width()): for col_pixel in range(self.image.height()): # Calculate a contrast correction factor factor = float(259 * (contrast + 255) / (255 * (259 - contrast))) current_val = QColor(self.image.pixel(row_pixel, col_pixel)) red = current_val.red() green = current_val.green() blue = current_val.blue() new_red = factor * (red - 128) + 128 new_green = factor * (green - 128) + 128 new_blue = factor * (blue - 128) + 128 new_value = qRgb(new_red, new_green, new_blue) self.image.setPixel(row_pixel, col_pixel, new_value) self.setPixmap(QPixmap().fromImage(self.image)) def changeHue(self): for row_pixel in range(self.image.width()): for col_pixel in range(self.image.height()): current_val = QColor(self.image.pixel(row_pixel, col_pixel)) hue = current_val.hue() current_val.setHsv(hue, current_val.saturation(), current_val.value(), current_val.alpha()) self.image.setPixelColor(row_pixel, col_pixel, current_val) self.setPixmap(QPixmap().fromImage(self.image)) def mousePressEvent(self, event): """Handle mouse press event.""" self.origin = event.pos() if not (self.rubber_band): self.rubber_band = QRubberBand(QRubberBand.Rectangle, self) self.rubber_band.setGeometry(QRect(self.origin, QSize())) self.rubber_band.show() #print(self.rubber_band.height()) print(self.rubber_band.x()) def mouseMoveEvent(self, event): """Handle mouse move event.""" self.rubber_band.setGeometry( QRect(self.origin, event.pos()).normalized()) def mouseReleaseEvent(self, event): """Handle when the mouse is released.""" self.rubber_band.hide()
from PyQt5.QtGui import QImage, QFont, QColor from PyQt5.QtCore import Qt import os, numpy as np from scipy.ndimage import sobel, gaussian_filter arr = np.zeros(texture.shape) displacement_weight = 2, 1.1 if normal_texture_filename != "": img = QImage(normal_texture_filename) img = img.convertToFormat(QImage.Format_RGB888) assert img.format() == QImage.Format_RGB888 assert img.width() * img.height() * 3 == img.byteCount() tex_arr = np.array(img.bits().asarray(img.byteCount())).reshape( img.width(), img.height(), 3) arr += tex_arr else: sigma = 1.3 tex_arr = texture.sum(axis=-1) / 3 tex_arr2 = np.zeros(arr.shape, dtype=np.float32) tex_arr2[:, :, 0] = 0.5 - sobel(tex_arr, 0) * displacement_weight[0] / 255.0 tex_arr2[:, :, 1] = 0.5 - sobel(tex_arr, 1) * displacement_weight[0] / 255.0 tex_arr2[:, :, 2] = 1 tex_arr2 /= np.linalg.norm(tex_arr2, axis=2, keepdims=True) tex_arr3 = gaussian_filter(tex_arr2, sigma=sigma) tex_arr3 /= np.linalg.norm(tex_arr3, axis=2, keepdims=True) tex_arr3[:, :, :2] *= displacement_weight[1] arr += tex_arr3
from PyQt5.QtGui import QImage, QFont, QColor from PyQt5.QtCore import Qt import os, numpy as np img = QImage(filename) img = img.convertToFormat(QImage.Format_RGB888) assert img.format() == QImage.Format_RGB888 assert img.width()*img.height()*3 == img.byteCount() if inscription != "": img2 = QImage(img.width(), img.height(), QImage.Format_RGB888) from PyQt5.QtGui import QPainter qp = QPainter() try: qp.begin(img2) #different results than painting on img! qp.drawImage(0,0,img) qp.setPen(QColor(255,185,50)) fx = 2 fy = 20 font = QFont("Arial", int(0.7*img.height()/fy)) qp.setFont(font) mx = img.width() / fx my = img.height() / fy for x in range(fx): for y in range(fy): qp.drawText(x*mx, y*my, mx, my, Qt.AlignCenter,inscription) finally: qp.end() img = img2
class BackgroundImage: """" Handle an bg_image/bg_image files: show bg_image in scene, rotate, cropped a region, etc. """ def __init__(self): self.img_file = None self.image = None # QImage self.scaling_factor = None # from displayed to original self.rotation = None self.rotated_image = None self.angle = None def show_in_scene(self, view): """ Rescale QPixmap to scene and show it. Parameters ---------- view: QGraphicsScene Returns ------- """ pixmap = QPixmap.fromImage(self.image) pixmap_scaled = pixmap.scaledToHeight(view.height()) view.scene.addPixmap(pixmap_scaled) orig_size = pixmap.size() scaled_size = pixmap_scaled.size() self.scaling_factor = scaled_size.height() / orig_size.height() def image_from_file(self, file_name): """ Load a TIFF bg_image from file `file_name` as a QImage and set it to `self.image`. Parameters ---------- file_name: str full path of bg_image file Returns ------- """ self.image = QImage(file_name) def rotate_image(self, angle): print('rotate_image is called') self.rotation = QTransform() self.rotation.rotateRadians(angle) self.angle = angle self.rotated_image = self.image.transformed(self.rotation) def map_item(self, item): """ Map item to rotated reference. :param item item in un-rotated coordinates :return: item in rotated coordinates """ if self.rotation is not None: return self.rotation.map(item) else: return None def del_rotated_image(self): del self.rotated_image def crop_region(self, coords, angle, file_name): """ :param coords: :param angle: :param file_name: :return: """ print('angle', angle) tl, bl, br, tr = coords print('Original coords', tl, br) """Scale polygon coordinates to original image size""" scaled_coords = [] for coord in coords: scaled_coords.append(coord / self.scaling_factor) tl, bl, br, tr = scaled_coords print('Scaled coords', tl, br) """Cast polygon coordinates to rotated image reference""" if self.rotation is not None: rotated_coords = [] for scaled_coord in scaled_coords: rotated_coords.append(self.map_item(scaled_coord)) tl, bl, br, tr = rotated_coords else: tl, bl, br, tr = scaled_coords print('Rotated coords', tl, br) corner = self.map_item(QPointF(0, 0)) print('new corner', corner) """Find rectangle to be cropped""" scaled_rect = QRectF(tl, br).toRect() # TODO rotation do not account for translating coordinate system. # TODO FIX THAT! # TODO there are large images in history. Images should never be outputted # TODO to git directory. Also, I need to remove that from history. # w = self.rotated_image.width() # h = self.rotated_image.height() # scaled_rect = QRectF(QPointF(0, 0), QPointF(w, h)).toRect() height = scaled_rect.height() width = scaled_rect.width() scaled_rect_size = QSize(width, height) try: """Create small image to paste grid square into""" cropped_image = self.rotated_image.copy(scaled_rect) """Use a `QPainter` to draw on `destination_image`""" bg_format = self.image.format() destination_image = QImage(scaled_rect_size, bg_format) destination_image.fill(Qt.transparent) # fill it w transparent bg painter = QPainter(destination_image) painter.drawImage(QRect(0, 0, width, height), cropped_image) painter.end() # generate an error if I don't call it except TypeError as err: print('No bg_image loaded?', err) except AttributeError as err: print('Could not copy pixmap?', err) except: print("Unexpected error:", sys.exc_info()[0]) raise else: destination_image.save(file_name + '.tif')