Qt/PyQt(/其他?):如何更改像素图中的特定颜色?

问题描述 投票:0回答:2

如何更改像素图中的特定颜色?例如,我有一个包含白色和黑色像素的像素图,我想将所有白色像素更改为蓝色,但保留黑色像素。或者也许将黑色更改为白色,将白色更改为蓝色...[我正在 Qt/PyQt 中寻找解决方案,但也许这是关于如何处理/组合像素图的一般问题。]

qt pyqt pixmap
2个回答
10
投票

您可以使用

createMaskFromColor
为白色像素创建位图,然后使用
drawPixmap
用另一种颜色覆盖它们。

    pix = QPixmap("test.png")
    mask = pix.createMaskFromColor(QColor(255, 255, 255), Qt.MaskOutColor)

    p = QPainter(pix)
    p.setPen(QColor(0, 0, 255))
    p.drawPixmap(pix.rect(), mask, mask.rect())
    p.end()

请注意,

createMaskFromColor
会将像素图转换为
QImage
,因此如果可能的话,您应该尝试直接使用
QImage


0
投票

有几个人问如何在不使用掩码的情况下完成位级操作(改变颜色)。为此,我们需要知道如何直接读取和设置像素。 QImage 就是为此类像素级操作而设计的,而标签和其他 QWidget 则需要 QPixmap。因此,我们还必须知道如何从 QPixmap 转换为 QImage 并再次转换回来。

这里是一个 PyQt6 示例(在 Windows 机器上用 Python 编写),它从头开始创建 QImage,使用 QPainter 绘制一些彩色圆圈,在屏幕上显示“之前”图像,然后检查每个像素,记录每个红色的计数像素,并将每个红色像素更改为白色,同时忽略所有其他颜色。我知道这段代码很丑陋。我按原样提供它是因为没有其他人提出一个例子来回答最初的问题。请将此代码视为启动您更深入研究的地方,并原谅其中的缺点。 -科学_1

import sys
from PyQt6.QtWidgets import QMainWindow, QApplication, QLabel
from PyQt6.QtCore import QSize,QPoint,QRect
from PyQt6.QtGui import QPainter, QPixmap, QPen, QColor, QImage
from random import choice, randint
from time import sleep

class myWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        COLORS = [QColor('red').rgb(),QColor('blue').rgb(),QColor('black').rgb(),QColor('green').rgb(),QColor('red')]

        img_1 = QPixmap(QSize(300,300)).toImage() # Create a 300x300 QPixmap image from scratch and convert it to a QImage.

        self.label = QLabel() # Declare a Qself.label for our widget.       
        self.label.resize(img_1.size())
        self.setCentralWidget(self.label)

        # Create our example image from scratch. A Green square with black outline, and a red diagonal line across it.
        img_1.fill(QColor('lightgreen')) # Fill the QImage with light-green.

        # Declare some colors that we will use with our QPens.
        targetColor = QColor('red') # We could use penColor = QColor(rgb(255,0,0,255)) here.

        # Draw a diagonal line across the QImage using QPainter
        artist = QPainter(img_1) # Higher an artist.

        for cnt in range(0,60): 
            artist.setPen(QPen(choice(COLORS),3)) # Have computer choose a color at random from our COLORS list.
            x = randint(0,300)
            y = randint(0,300)
            r = randint(15,40)
            artist.drawEllipse(x,y,r,r) # For a circle type ellipse, the length and width must be the same.
        artist.end() # Dismiss the artist.

        # You don't actually need QPainter to draw on a QImage, but without it, you must code everything it does yourself.
        # Also, setPixel() can't handle attempts to set pixels that are off screen, like QPainter can,
        # So you must be careful to stay in bounds.
        # Here is an example of setting pixels without using QPainter.
        diagonal_Color = QColor("brown").rgba()
        for a in range(0,298):
            img_1.setPixelColor(a,a,diagonal_Color) # The setPixel() or setPixelColor() commands can 
            img_1.setPixel(a+1,a,diagonal_Color)    # be used to set a pixel in an image.   
            img_1.setPixel(a+2,a,diagonal_Color)    # What's the difference? Beats me. If one gives you fits, try the other.    

        self.label.setPixmap(QPixmap.fromImage(img_1))
        self.show()

        # Here we tease the viewer, then suspend the program for three seconds so the 'before' image can be studied.
        print(' Wait for it...') # Tease
        sleep(3) # <-- A quick & dirty pause. For real code, use a one-off signal emitter, or a user-driven event. 

        # In this section, we progress incrementally through all of the pixels, checking the colors.
        # Any red pixels are over-written with white. This is a slow process. For speed, use a mask with QPainter.
        # But pixel-level manipulation has its place, if speed is not a criteria.

        rcount = 0
        x = self.label.size().width()  
        y = self.label.size().height() 

        for row in range(0,y):
            for column in range(0,x):
                pixel_color = img_1.pixelColor(QPoint(column,row)) # Read the pixel color from the QImage.
                if pixel_color == targetColor: # If the pixel is red..
                    rcount += 1 # Incriment the pixel count.
                    img_1.setPixel(column,row,QColor("white").rgb())    # Change the red pixel to white.

                    '''     
                    # If you want to examine the rgb colors individually, you can use .red(), .green(), .blue(), and .alpha()
                    r = pixel_color.red()
                    g = pixel_color.green()
                    b = pixel_color.blue()
                    a = pixel_color.alpha()                 
                    print('pixel_color RGBA = ('+str(r)+', '+str(g)+', '+str(b)+', '+str(a)+')')
                    ''' 

        self.label.setPixmap(QPixmap.fromImage(img_1))  # Convert the Image to a QPixmap, and put it on the label.
        print('\n Finished.')
        print(" All red pixels have been changed to white.")
        print(" Total number of pixels changed:",rcount)
        print("\n Close Window to Quit")            

        self.setCentralWidget(self.label) # A label, being a widget, and can be directly assigned to a QWindow.
        self.show()                       # But if you need several widgets on the screen, use one of the layouts and assign that.

app = QApplication(sys.argv)
window = myWindow()
window.show()
app.exec()
© www.soinside.com 2019 - 2024. All rights reserved.