บังคับให้ค่าเฉลี่ยบนรูปภาพ


20

เขียนโปรแกรมที่ใช้ภาพtruecolorมาตรฐานและสีRGB 24 บิตเดียว(สามตัวเลขจาก 0 ถึง 255) ปรับเปลี่ยนภาพอินพุต (หรือเอาท์พุทของภาพใหม่ที่มีขนาดเท่ากัน) เพื่อให้สีเฉลี่ยนั้นเป็นสีเดียวที่ป้อนเข้า คุณอาจจะปรับเปลี่ยนพิกเซลในภาพที่นำเข้าในแบบที่คุณต้องการเพื่อให้บรรลุนี้ใด ๆแต่เป้าหมายคือการทำให้การเปลี่ยนสีเป็นที่สังเกตสายตาที่เป็นไปได้

สีเฉลี่ยของภาพ RGB มันชุดของสามมัชฌิมเลขคณิตหนึ่งสำหรับแต่ละช่องสี ค่าเฉลี่ยสีแดงคือผลรวมของค่าสีแดงในทุกพิกเซลในภาพหารด้วยจำนวนพิกเซลทั้งหมด (พื้นที่ภาพ) ปัดลงเป็นจำนวนเต็มที่ใกล้ที่สุด ค่าเฉลี่ยสีเขียวและสีน้ำเงินถูกคำนวณในลักษณะเดียวกัน

นี้งูหลาม 2 (กับPIL ) สคริปต์สามารถคำนวณค่าเฉลี่ยของสีมากที่สุดรูปแบบไฟล์ภาพ:

from PIL import Image
print 'Enter image file'
im = Image.open(raw_input()).convert('RGB')
pixels = im.load()
avg = [0, 0, 0]
for x in range(im.size[0]):
    for y in range(im.size[1]):
        for i in range(3):
            avg[i] += pixels[x, y][i]
print 'The average color is', tuple(c // (im.size[0] * im.size[1]) for c in avg)

(มีโปรแกรมสีเฉลี่ยที่คล้ายกันที่นี่แต่ไม่จำเป็นต้องทำการคำนวณเดียวกันทั้งหมด)

ข้อกำหนดหลักสำหรับโปรแกรมของคุณคือสำหรับภาพที่เข้ามาใด ๆสีเฉลี่ยของผลลัพธ์ที่สอดคล้องกันนั้นจะต้องตรงกับสีที่ได้รับการป้อนเข้า - ตามที่ตัดสินโดยตัวอย่างของ Python หรือรหัสที่เทียบเท่า ภาพที่ส่งออกจะต้องมีขนาดที่แน่นอนเหมือนกับภาพที่ป้อน

เพื่อให้คุณได้ในทางเทคนิคสามารถส่งโปรแกรมที่เพียงแค่สีอินพุตทั้งสีเฉลี่ยระบุ (เพราะค่าเฉลี่ยมักจะเป็นสีที่) แต่นี่คือการประกวดความนิยม - ส่งที่มีคะแนนเสียงสูงสุดจะเป็นผู้ชนะและเช่นจิ๊บจ๊อย การส่งจะไม่ได้รับ upvotes มากมาย ความคิดใหม่ ๆ เช่นการใช้ประโยชน์จากนิสัยใจคอในสายตามนุษย์หรือทำให้ภาพหดตัวลงและวาดเส้นขอบสีรอบ ๆ ภาพ (หวังว่า) คุณจะได้รับการโหวต

โปรดทราบว่าการผสมสีและรูปภาพโดยเฉลี่ยทำให้จำเป็นต้องมีการเปลี่ยนสีอย่างเห็นได้ชัด ตัวอย่างเช่นหากสีเฉลี่ยเพื่อจับคู่เป็นสีดำ (0, 0, 0) ภาพอินพุตใด ๆจะต้องทำให้เป็นสีดำสนิทเพราะหากพิกเซลใด ๆ มีค่าที่ไม่เป็นศูนย์พวกเขาก็จะทำให้ค่าเฉลี่ยไม่เป็นศูนย์ด้วย จํากัดการปัดเศษผิดพลาด) เก็บข้อ จำกัด ไว้ในใจเมื่อลงคะแนน

ทดสอบภาพ

ภาพบางภาพและสีเริ่มต้นเฉลี่ยที่จะเล่นด้วย คลิกเพื่อดูขนาดเต็ม

A.เฉลี่ย (127, 127, 127)

จากfejesjocoของภาพที่มีทุกสี คำตอบ พบต้นฉบับในบล็อกของเขา

B.โดยเฉลี่ย (62, 71, 73)

โยโกฮามา ให้บริการโดยGeobits

C.เฉลี่ย (115, 112, 111)

โตเกียว ให้บริการโดยGeobits

D.เฉลี่ย (154, 151, 154)

Escher ของน้ำตก เป็นต้นฉบับ

E.เฉลี่ย (105, 103, 102)

mount Shasta จัดหาให้โดยฉัน

F.โดยเฉลี่ย (75, 91, 110)

สตาร์รี่ไนท์

หมายเหตุ

  • รูปแบบอินพุตและเอาต์พุตที่แน่นอนและประเภทไฟล์รูปภาพที่โปรแกรมของคุณใช้นั้นมีความสำคัญมาก เพียงให้แน่ใจว่ามีความชัดเจนในการใช้โปรแกรมของคุณ
  • มันอาจเป็นความคิดที่ดี (แต่ไม่ใช่ความต้องการด้านเทคนิค) ว่าหากภาพมีสีเฉลี่ยเป้าหมายอยู่แล้วควรส่งออกตามที่เป็นอยู่
  • โปรดโพสต์ภาพทดสอบที่มีอินพุตสีเฉลี่ยเป็น (150, 100, 100) หรือ (75, 91, 110) ดังนั้นผู้ลงคะแนนสามารถเห็นอินพุตเดียวกันในโซลูชันที่แตกต่างกัน (การโพสต์ตัวอย่างเพิ่มเติมนอกเหนือจากนี้เป็นสิ่งที่ดีแม้สนับสนุน)

2
ผู้เข้าร่วมจะต้องเลือกสีอินพุตที่ใช้เพื่อแสดงให้เห็นถึงประสิทธิภาพของวิธีแก้ปัญหาของพวกเขา นั่นไม่ได้ทำให้คนยากที่จะเปรียบเทียบโซลูชั่นหรือไม่ ในกรณีที่รุนแรงใครบางคนสามารถเลือกสีอินพุตที่คล้ายกับค่าเฉลี่ยของภาพมากและดูเหมือนว่าโซลูชันของพวกเขาจะมีประสิทธิภาพมาก
Reto Koradi

1
@ vihan1086 หากฉันเข้าใจถูกต้องสีเฉลี่ยจะถูกระบุเป็นอินพุตสี RGB 24 บิตซึ่งไม่พบจากภาพอินพุต
trichoplax

3
อาจน่าสนใจที่จะใช้การตีความของ @ vihan1086 และใช้ภาพตัวอย่างเป็นแหล่งที่มาของสีอินพุตดังนั้นภาพหนึ่งภาพจึงแสดงเป็นสีเฉลี่ยของอีกภาพหนึ่ง วิธีนี้สามารถเปรียบเทียบคำตอบที่ต่างกันได้อย่างยุติธรรม
trichoplax

ปัญหาหลักของเรื่องนี้คือพวกเขาส่วนใหญ่มีค่าเฉลี่ยที่ใกล้เคียงกับสีเทามาก Starry Nightน่าจะไกลที่สุด แต่ส่วนที่เหลือก็ค่อนข้างเรียบ
Geobits

@RetoKoradi หวังว่าผู้ออกเสียงลงคะแนนจะฉลาดพอที่จะคำนึงถึงสิ่งต่าง ๆ แม้ว่าฉันจะได้เพิ่มข้อความเกี่ยวกับสีเริ่มต้นที่ควรใช้
งานอดิเรกของ Calvin

คำตอบ:


11

Python 2 + PIL การปรับสีแบบง่าย

from PIL import Image
import math

INFILE = "street.jpg"
OUTFILE = "output.png"
AVERAGE = (150, 100, 100)

im = Image.open(INFILE)
im = im.convert("RGB")
width, height = prev_size = im.size
pixels = {(x, y): list(im.getpixel((x, y)))
          for x in range(width) for y in range(height)}

def get_avg():
    total_rgb = [0, 0, 0]

    for x in range(width):
        for y in range(height):
            for i in range(3):
                total_rgb[i] += int(pixels[x, y][i])

    return [float(x)/(width*height) for x in total_rgb]

curr_avg = get_avg()

while tuple(int(x) for x in curr_avg) != AVERAGE:
    print curr_avg   
    non_capped = [0, 0, 0]
    total_rgb = [0, 0, 0]

    for x in range(width):
        for y in range(height):
            for i in range(3):
                if curr_avg[i] < AVERAGE[i] and pixels[x, y][i] < 255:
                    non_capped[i] += 1
                    total_rgb[i] += int(pixels[x, y][i])

                elif curr_avg[i] > AVERAGE[i] and pixels[x, y][i] > 0:
                    non_capped[i] += 1
                    total_rgb[i] += int(pixels[x, y][i])

    ratios = [1 if z == 0 else
              x/(y/float(z))
              for x,y,z in zip(AVERAGE, total_rgb, non_capped)]

    for x in range(width):
        for y in range(height):
            col = []

            for i in range(3):
                new_col = (pixels[x, y][i] + 0.01) * ratios[i]
                col.append(min(255, max(0, new_col)))

            pixels[x, y] = tuple(col)

    curr_avg = get_avg()

print curr_avg

for pixel in pixels:
    im.putpixel(pixel, tuple(int(x) for x in pixels[pixel]))

im.save(OUTFILE)

นี่คือวิธีการไร้เดียงสาที่ควรทำหน้าที่เป็นพื้นฐานที่ดี ในการคำนวณซ้ำแต่ละครั้งเราเปรียบเทียบค่าเฉลี่ยปัจจุบันของเรากับค่าเฉลี่ยที่ต้องการและปรับขนาด RGB ของแต่ละพิกเซลตามอัตราส่วน เราต้องระวังให้ดีด้วยเหตุผลสองประการ:

  • การขยายสเกล 0 ยังคงให้ผลลัพธ์เป็น 0 ดังนั้นก่อนที่เราจะขยายเราจะเพิ่มบางสิ่งเล็ก ๆ (ที่นี่0.01)

  • ค่า RGB อยู่ระหว่าง 0 ถึง 255 ดังนั้นเราจำเป็นต้องปรับอัตราส่วนตามเพื่อชดเชยความจริงที่ว่าการปรับขนาดพิกเซลที่ปกคลุมไม่ได้ทำอะไรเลย

รูปภาพบันทึกเป็น PNG เนื่องจากการบันทึกเป็น JPG ดูเหมือนจะทำให้ค่าเฉลี่ยของสียุ่งเหยิง

ตัวอย่างผลลัพธ์

(40, 40, 40)

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

(150, 100, 100)

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

(75, 91, 110), จานสีของ Starry Night

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


2
แน่นอนคุณต้องการใช้รูปแบบภาพที่มีการบีบอัดแบบไม่สูญเสียสำหรับสิ่งนี้ ดังนั้น JPEG จึงไม่ใช่ตัวเลือกที่ดี
Reto Koradi

คุณสามารถไว้วางใจ Sp เพื่อแก้ปัญหาความท้าทายภาพที่ยอดเยี่ยมได้เสมอ
Alex A.

6

C ++, การแก้ไขแกมม่า

นี่เป็นการปรับความสว่างของภาพโดยใช้การแก้ไขแกมม่าอย่างง่ายโดยใช้ค่าแกมม่าที่แยกต่างหากสำหรับแต่ละองค์ประกอบเพื่อให้ตรงกับค่าเฉลี่ยเป้าหมาย

ขั้นตอนระดับสูงคือ:

  1. อ่านภาพและแยกฮิสโตแกรมสำหรับองค์ประกอบแต่ละสี
  2. ทำการค้นหาไบนารีของค่าแกมมาสำหรับแต่ละองค์ประกอบ การค้นหาแบบไบนารีจะดำเนินการกับค่าแกมมาจนกระทั่งฮิสโตแกรมที่ได้นั้นมีค่าเฉลี่ยที่ต้องการ
  3. อ่านภาพเป็นครั้งที่สองและใช้การแก้ไขแกมม่า

อินพุต / เอาต์พุตรูปภาพทั้งหมดใช้ไฟล์ PPM ใน ASCII รูปภาพถูกแปลงจาก / เป็น PNG โดยใช้ GIMP รหัสถูกเรียกใช้บน Mac การแปลงรูปภาพเสร็จแล้วบน Windows

รหัส:

#include <cmath>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <iostream>

static inline int mapVal(int val, float gamma)
{
    float relVal = (val + 1.0f) / 257.0f;
    float newRelVal = powf(relVal, gamma);

    int newVal = static_cast<int>(newRelVal * 257.0f - 0.5f);
    if (newVal < 0)
    {
        newVal = 0;
    }
    else if (newVal > 255)
    {
        newVal = 255;
    }

    return newVal;
}

struct Histogram
{
    Histogram();

    bool read(const std::string fileName);
    int getAvg(int colIdx) const;
    void adjust(const Histogram& origHist, int colIdx, float gamma);

    int pixCount;
    std::vector<int> freqA[3];
};

Histogram::Histogram()
  : pixCount(0)
{
    for (int iCol = 0; iCol < 3; ++iCol)
    {
        freqA[iCol].resize(256, 0);
    }
}

bool Histogram::read(const std::string fileName)
{
    for (int iCol = 0; iCol < 3; ++iCol)
    {
        freqA[iCol].assign(256, 0);
    }

    std::ifstream inStrm(fileName);

    std::string format;
    inStrm >> format;
    if (format != "P3")
    {
        std::cerr << "invalid PPM header" << std::endl;
        return false;
    }

    int w = 0, h = 0;
    inStrm >> w >> h;
    if (w <= 0 || h <= 0)
    {
        std::cerr << "invalid size" << std::endl;
        return false;
    }

    int maxVal = 0;
    inStrm >> maxVal;
    if (maxVal != 255)
    {
        std::cerr << "invalid max value (255 expected)" << std::endl;
        return false;
    }

    pixCount = w * h;

    int sumR = 0, sumG = 0, sumB = 0;
    for (int iPix = 0; iPix < pixCount; ++iPix)
    {
        int r = 0, g = 0, b = 0;
        inStrm >> r >> g >> b;
        ++freqA[0][r];
        ++freqA[1][g];
        ++freqA[2][b];
    }

    return true;
}

int Histogram::getAvg(int colIdx) const
{
    int avg = 0;
    for (int val = 0; val < 256; ++val)
    {
        avg += freqA[colIdx][val] * val;
    }

    return avg / pixCount;
}

void Histogram::adjust(const Histogram& origHist, int colIdx, float gamma)
{
    freqA[colIdx].assign(256, 0);

    for (int val = 0; val < 256; ++val)
    {
        int newVal = mapVal(val, gamma);
        freqA[colIdx][newVal] += origHist.freqA[colIdx][val];
    }
}

void mapImage(const std::string fileName, float gammaA[])
{
    std::ifstream inStrm(fileName);

    std::string format;
    inStrm >> format;

    int w = 0, h = 0;
    inStrm >> w >> h;

    int maxVal = 0;
    inStrm >> maxVal;

    std::cout << "P3" << std::endl;
    std::cout << w << " " << h << std::endl;
    std::cout << "255" << std::endl;

    int nPix = w * h;

    for (int iPix = 0; iPix < nPix; ++iPix)
    {
        int inRgb[3] = {0};
        inStrm >> inRgb[0] >> inRgb[1] >> inRgb[2];

        int outRgb[3] = {0};
        for (int iCol = 0; iCol < 3; ++iCol)
        {
            outRgb[iCol] = mapVal(inRgb[iCol], gammaA[iCol]);
        }

        std::cout << outRgb[0] << " " << outRgb[1] << " "
                  << outRgb[2] << std::endl;
    }
}

int main(int argc, char* argv[])
{
    if (argc < 5)
    {
        std::cerr << "usage: " << argv[0]
                  << " ppmFileName targetR targetG targetB"
                  << std::endl;
        return 1;
    }

    std::string inFileName = argv[1];

    int targAvg[3] = {0};
    std::istringstream strmR(argv[2]);
    strmR >> targAvg[0];
    std::istringstream strmG(argv[3]);
    strmG >> targAvg[1];
    std::istringstream strmB(argv[4]);
    strmB >> targAvg[2];

    Histogram origHist;
    if (!origHist.read(inFileName))
    {
        return 1;
    }

    Histogram newHist(origHist);
    float gammaA[3] = {0.0f};

    for (int iCol = 0; iCol < 3; ++iCol)
    {
        float minGamma = 0.0f;
        float maxGamma = 1.0f;
        for (;;)
        {
            newHist.adjust(origHist, iCol, maxGamma);
            int avg = newHist.getAvg(iCol);
            if (avg <= targAvg[iCol])
            {
                break;
            }
            maxGamma *= 2.0f;
        }

        for (;;)
        {
            float midGamma = 0.5f * (minGamma + maxGamma);

            newHist.adjust(origHist, iCol, midGamma);
            int avg = newHist.getAvg(iCol);
            if (avg < targAvg[iCol])
            {
                maxGamma = midGamma;
            }
            else if (avg > targAvg[iCol])
            {
                minGamma = midGamma;
            }
            else
            {
                gammaA[iCol] = midGamma;
                break;
            }
        }
    }

    mapImage(inFileName, gammaA);

    return 0;
}

รหัสนั้นค่อนข้างตรงไปตรงมา รายละเอียดที่ละเอียดอ่อน แต่สำคัญคือหนึ่งในขณะที่ค่าสีอยู่ในช่วง [0, 255] ฉันจับคู่มันกับเส้นโค้งแกมม่าราวกับว่าช่วงนั้นเป็น [-1, 256] สิ่งนี้อนุญาตให้ค่าเฉลี่ยถูกบังคับให้เป็น 0 หรือ 255 มิฉะนั้นจะเป็น 0 เสมอ 0 และ 255 จะยังคง 255 เสมอซึ่งอาจไม่อนุญาตสำหรับค่าเฉลี่ย 0/255

ใช้:

  1. บันทึกรหัสในไฟล์ที่มีนามสกุล.cppเช่นforce.cppเช่น
  2. รวบรวมกับ c++ -o force -O2 force.cppคอมไพล์ด้วย
  3. ./force input.ppm targetR targetG target >output.ppmทำงานด้วย

เอาต์พุตตัวอย่างสำหรับ 40, 40, 40

โปรดทราบว่ารูปภาพสำหรับตัวอย่างที่มีขนาดใหญ่กว่าทั้งหมดจะถูกรวมเป็น JPEG เนื่องจากมีขนาดเกินขนาด SE ที่ จำกัด เป็น PNG เนื่องจาก JPEG เป็นรูปแบบการบีบอัดที่สูญเสียจึงอาจไม่ตรงกับค่าเฉลี่ยเป้าหมาย ฉันมีไฟล์ทั้งหมดในเวอร์ชัน PNG ซึ่งตรงกันทั้งหมด

AF1 BF1 CF1 DF1 EF1 FF1

เอาต์พุตตัวอย่างสำหรับ 150, 100, 100:

Af2 Bf2 CF2 Df2 EF2 FF2

เอาต์พุตตัวอย่างสำหรับ 75, 91, 110:

AF3 BF3 CF3 Df3 EF3 FF3


ฉันต้องย่อขนาดรูปภาพอื่น ๆ ลงจนเกินขีด จำกัด - ลองดูสิ
Sp3000

@ Sp3000 ตกลงได้ภาพทั้งหมดที่รวมอยู่ในขณะนี้ ยังมีภาพขนาดย่อในขณะนี้ ฉันลงเอยด้วยการใช้รุ่น JPEG สำหรับวัตถุที่มีขนาดใหญ่ ที่จริงแล้วหนึ่งในนั้นมีขนาดต่ำกว่าขีด จำกัด แต่ดูเหมือนว่าจะถูกแปลงเป็น JPEG โดยอัตโนมัติ ตัวอย่างแรกและสุดท้ายยังคงเป็น PNG
Reto Koradi

2

Python 2 + PIL

from PIL import Image
import random
import math

SOURCE = 'input.png'
OUTPUT = 'output.png'
AVERAGE = [150, 100, 100]

im = Image.open(SOURCE).convert('RGB')
pixels = im.load()
w = im.size[0]
h = im.size[1]
npixels = w * h

maxdiff = 0.1

# for consistent results...
random.seed(42)
order = range(npixels)
random.shuffle(order)

def calc_sum(pixels, w, h):
    sums = [0, 0, 0]
    for x in range(w):
        for y in range(h):
            for i in range(3):
                sums[i] += pixels[x, y][i]
    return sums

def get_coordinates(index, w):
    return tuple([index % w, index // w])

desired_sums = [AVERAGE[0] * npixels, AVERAGE[1] * npixels, AVERAGE[2] * npixels]

sums = calc_sum(pixels, w, h)
for i in range(3):
    while sums[i] != desired_sums[i]:
        for j in range(npixels):
            if sums[i] == desired_sums[i]:
                break
            elif sums[i] < desired_sums[i]:
                coord = get_coordinates(order[j], w)
                pixel = list(pixels[coord])
                delta = int(maxdiff * (255 - pixel[i]))
                if delta == 0 and pixel[i] != 255:
                    delta = 1
                delta = min(delta, desired_sums[i] - sums[i])

                sums[i] += delta
                pixel[i] += delta
                pixels[coord] = tuple(pixel)
            else:
                coord = get_coordinates(order[j], w)
                pixel = list(pixels[coord])
                delta = int(maxdiff * pixel[i])
                if delta == 0 and pixel[i] != 0:
                    delta = 1
                delta = min(delta, sums[i] - desired_sums[i])

                sums[i] -= delta
                pixel[i] -= delta
                pixels[coord] = tuple(pixel)

# output image
for x in range(w):
    for y in range(h):
        im.putpixel(tuple([x, y]), pixels[tuple([x, y])])

im.save(OUTPUT)

ซึ่งจะวนซ้ำผ่านแต่ละพิกเซลในลำดับแบบสุ่มและลดระยะห่างระหว่างแต่ละองค์ประกอบของสีของพิกเซลและ255หรือ0(ขึ้นอยู่กับว่าค่าเฉลี่ยในปัจจุบันน้อยกว่าหรือสูงกว่าค่าเฉลี่ยที่ต้องการ) ระยะทางจะลดลงโดยปัจจัยคูณคงที่ ทำซ้ำจนกว่าจะได้ค่าเฉลี่ยที่ต้องการ การลดอย่างน้อยก็ตลอดเวลา1เว้นแต่ว่าสีจะเป็น255(หรือ0) เพื่อให้แน่ใจว่าการประมวลผลจะไม่หยุดทำงานเมื่อพิกเซลอยู่ใกล้กับสีขาวหรือสีดำ

ตัวอย่างผลลัพธ์

(40, 40, 40)

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

(150, 100, 100)

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

(75, 91, 110)

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


1

ชวา

วิธีการตาม RNG ช้าเล็กน้อยสำหรับภาพอินพุตขนาดใหญ่

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.*;

import javax.imageio.ImageIO;


public class Averager {
    static Random r;
    static long sigmaR=0,sigmaG=0,sigmaB=0;
    static int w,h;
    static int rbar,gbar,bbar;
    static BufferedImage i;
    private static File file;
    static void upRed(){
        int x=r.nextInt(w);
        int y=r.nextInt(h);
        Color c=new Color(i.getRGB(x, y));
        if(c.getRed()==255)return;
        sigmaR++;
        c=new Color(c.getRed()+1,c.getGreen(),c.getBlue());
        i.setRGB(x, y,c.getRGB());
    }
    static void downRed(){
        int x=r.nextInt(w);
        int y=r.nextInt(h);
        Color c=new Color(i.getRGB(x, y));
        if(c.getRed()==0)return;
        sigmaR--;
        c=new Color(c.getRed()-1,c.getGreen(),c.getBlue());
        i.setRGB(x, y,c.getRGB());
    }
    static void upGreen(){
        int x=r.nextInt(w);
        int y=r.nextInt(h);
        Color c=new Color(i.getRGB(x, y));
        if(c.getGreen()==255)return;
        sigmaG++;
        c=new Color(c.getRed(),c.getGreen()+1,c.getBlue());
        i.setRGB(x, y,c.getRGB());
    }
    static void downGreen(){
        int x=r.nextInt(w);
        int y=r.nextInt(h);
        Color c=new Color(i.getRGB(x, y));
        if(c.getGreen()==0)return;
        sigmaG--;
        c=new Color(c.getRed(),c.getGreen()-1,c.getBlue());
        i.setRGB(x,y,c.getRGB());
    }
    static void upBlue(){
        int x=r.nextInt(w);
        int y=r.nextInt(h);
        Color c=new Color(i.getRGB(x, y));
        if(c.getBlue()==255)return;
        sigmaB++;
        c=new Color(c.getRed(),c.getGreen(),c.getBlue()+1);
        i.setRGB(x, y,c.getRGB());
    }
    static void downBlue(){
        int x=r.nextInt(w);
        int y=r.nextInt(h);
        Color c=new Color(i.getRGB(x, y));
        if(c.getBlue()==0)return;
        sigmaB--;
        c=new Color(c.getRed(),c.getGreen(),c.getBlue()-1);
        i.setRGB(x,y,c.getRGB());
    }
    public static void main(String[]a) throws Exception{
        Scanner in=new Scanner(System.in);
        i=ImageIO.read(file=new File(in.nextLine()));
        rbar=in.nextInt();
        gbar=in.nextInt();
        bbar=in.nextInt();
        w=i.getWidth();
        h=i.getHeight();
        final int npix=w*h;
        r=new Random(npix*(long)i.hashCode());
        for(int x=0;x<w;x++){
            for(int y=0;y<h;y++){
                Color c=new Color(i.getRGB(x, y));
                sigmaR+=c.getRed();
                sigmaG+=c.getGreen();
                sigmaB+=c.getBlue();
            }
        }
        while(sigmaR/npix<rbar){
            upRed();
        }
        while(sigmaR/npix>rbar){
            downRed();
        }
        while(sigmaG/npix<gbar){
            upGreen();
        }
        while(sigmaG/npix>gbar){
            downGreen();
        }
        while(sigmaB/npix<bbar){
            upBlue();
        }
        while(sigmaB/npix>bbar){
            downBlue();
        }
        String k=file.getName().split("\\.")[0];
        ImageIO.write(i,"png",new File(k="out_"+k+".png"));
    }
}

แบบทดสอบ:

(40,40,40)

ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่

(150,100,100)

ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่

(75,91,110)

ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่ป้อนคำอธิบายรูปภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.