কোনও গ্রেস্কেল চিত্র নয় D


23

আপনার নিজের অ্যালগোরিদমের সাথে খাঁটি কালো এবং সাদা কোনও ধূসর রঙের চিত্রটি ither

গাইডলাইনস: আপনাকে অবশ্যই নিজের নতুন অ্যালগরিদম নিয়ে আসতে হবে। আপনি প্রাক-বিদ্যমান অ্যালগরিদমগুলি ব্যবহার করতে পারবেন না (উদাঃ ফ্লয়েড-স্টেইনবার্গ) তবে আপনি সাধারণ কৌশলটি ব্যবহার করতে পারেন। আপনার প্রোগ্রামটি অবশ্যই একটি চিত্র পড়তে এবং একই আকারে একটি চিত্র তৈরি করতে সক্ষম হতে হবে। এটি একটি জনপ্রিয়তার প্রতিযোগিতা, সুতরাং যে কেউ সেরা (মূলের নিকটতম) এবং সর্বাধিক সৃজনশীল (ভোট দ্বারা নির্ধারিত) জিতায়। কোডটি সংক্ষিপ্ত থাকলে বোনাস, যদিও এটি প্রয়োজনীয় নয়।

ইনপুট হিসাবে আপনি যা চান গ্রেস্কেল চিত্রটি ব্যবহার করতে পারেন, এটি 300x300 এর চেয়ে বড় হওয়া উচিত। যে কোনও ফাইল ফর্ম্যাট ঠিক আছে।

উদাহরণ ইনপুট:

কুকুরছানা

উদাহরণ আউটপুট:

ডিথারকৃত

এটি একটি খুব ভাল কাজ, কিন্তু এখনও দৃশ্যমান লাইন এবং নিদর্শন আছে।


4
একটি আকর্ষণীয় চ্যালেঞ্জের জন্য +1, তবে আমি মনে করি এটি [কোড-গল্ফ] (একটি স্পেস সহ) বা অন্য কোনও সম্পূর্ণ উদ্দেশ্যমূলক মানদণ্ড হিসাবে আরও ভাল।
ডুরকনব

2
কোড-আকার, গতি এবং মেমরির ব্যবহারের সমস্যাটি হ'ল উত্তরটি বৈধ হওয়ার জন্য ফলাফলটি কীভাবে সনাক্তযোগ্য তা অবশ্যই সনাক্ত করার জন্য আপনার একটি উদ্দেশ্য সীমার প্রয়োজন হবে, এটিও বেশ অসম্ভব। জনপ্রিয়তা প্রতিযোগিতাটি বোঝা যায়, তবে কোডটিতে কোনও বিধিনিষেধ ছাড়াই লোকদের বাক্সের বাইরে চিন্তাভাবনা করার কোনও প্ররোচনা নেই। আমি তার চেয়ে ভাল একটি চালাক উত্তর উপস্থাপন করব তবে এটি সর্বোত্তম ফলাফল দেয় কারণ এটি কেবলমাত্র একটি বিদ্যমান অ্যালগরিদম কার্যকর করেছে। তবে আপনি বর্তমানে উত্তরোত্তরগুলি উত্সাহিত করছেন।
মার্টিন ইন্ডার 21

3
কোন দিকটি পড়েছে তা নির্ধারণ করতে একটি অ্যালগরিদম এবং এর কৌশলটির মধ্যে রেখাটি খুব পাতলা।
পিটার টেলর

2
আমি মনে করি ফলাফলগুলি যদি তারা সবাই একই চিত্র থেকে ফলাফল দেখায় তবে তুলনা করা অনেক সহজ হবে।
জোয়েটউইল

3
আপনি কি ছবিটির উত্স যুক্ত করতে পারেন? (আমি মনে করি না যে কেউ এখানে তার ছবিটি দেখে রেগে যাবে তবে উত্সটি উদ্ধৃত করা ন্যায়সঙ্গত)
এএল

উত্তর:


16

ফোরট্রান

ঠিক আছে, আমি FITS নামে একটি অস্পষ্ট চিত্র বিন্যাস ব্যবহার করছি যা জ্যোতির্বিদ্যার জন্য ব্যবহৃত হয়। এর অর্থ এই জাতীয় চিত্রগুলি পড়ার এবং লেখার জন্য একটি ফোর্টরান গ্রন্থাগার রয়েছে। এছাড়াও, ইমেজম্যাগিক এবং গিম্প উভয়ই ফিটস চিত্রগুলি পড়তে / লিখতে পারে।

আমি যে অ্যালগরিদমটি ব্যবহার করি তা "সিয়েরা লাইট" সরে যাওয়ার উপর ভিত্তি করে, তবে দুটি উন্নতি সহ:
ক) আমি 4/5 ফ্যাক্টর দ্বারা প্রচারিত ত্রুটি হ্রাস করি।
খ) আমি সংশ্লেষের ম্যাট্রিক্সের যোগফলকে স্থির রাখতে গিয়ে এলোমেলো পরিবর্তনের প্রবর্তন করি।
একসাথে এইগুলি ওপস উদাহরণে প্রদর্শিত নিদর্শনগুলি সম্পূর্ণরূপে বাদ দেয়।

ধরে নিই যে আপনার সিএফআইটিএসআইও লাইব্রেরি ইনস্টল করা আছে, তার সাথে সংকলন করুন

gfortran -lcfitsio dither.f90

ফাইলের নামগুলি হার্ড-কোডড (এটি ঠিক করার পক্ষে বিরক্ত করা যায় না)।

কোড:

program dither
  integer              :: status,unit,readwrite,blocksize,naxes(2),nfound
  integer              :: group,npixels,bitpix,naxis,i,j,fpixel,un
  real                 :: nullval,diff_mat(3,2),perr
  real, allocatable    :: image(:,:), error(:,:)
  integer, allocatable :: seed(:)
  logical              :: anynull,simple,extend
  character(len=80)    :: filename

  call random_seed(size=Nrand)
  allocate(seed(Nrand))
  open(newunit=un,file="/dev/urandom",access="stream",&
       form="unformatted",action="read",status="old")
  read(un) seed
  close(un)
  call random_seed(put=seed)
  deallocate(seed)

  status=0
  call ftgiou(unit,status)
  filename='PUPPY.FITS'
  readwrite=0
  call ftopen(unit,filename,readwrite,blocksize,status)
  call ftgknj(unit,'NAXIS',1,2,naxes,nfound,status)
  call ftgidt(unit,bitpix,status)
  npixels=naxes(1)*naxes(2)
  group=1
  nullval=-999
  allocate(image(naxes(1),naxes(2)))
  allocate(error(naxes(1)+1,naxes(2)+1))
  call ftgpve(unit,group,1,npixels,nullval,image,anynull,status)
  call ftclos(unit, status)
  call ftfiou(unit, status)

  diff_mat=0.0
  diff_mat(3,1) = 2.0 
  diff_mat(1,2) = 1.0
  diff_mat(2,2) = 1.0
  diff_mat=diff_mat/5.0

  error=0.0
  perr=0
  do j=1,naxes(2)
    do i=1,naxes(1)
      p=max(min(image(i,j)+error(i,j),255.0),0.0)
      if (p < 127.0) then
        perr=p
        image(i,j)=0.0
      else
        perr=p-255.0
        image(i,j)=255.0
      endif
      call random_number(r)
      r=0.6*(r-0.5)
      error(i+1,j)=  error(i+1,j)  +perr*(diff_mat(3,1)+r)
      error(i-1,j+1)=error(i-1,j+1)+perr*diff_mat(1,2)
      error(i  ,j+1)=error(i ,j+1) +perr*(diff_mat(2,2)-r)
    end do
  end do

  call ftgiou(unit,status)
  blocksize=1
  filename='PUPPY-OUT.FITS'
  call ftinit(unit,filename,blocksize,status)
  simple=.true.
  naxis=2
  extend=.true.
  call ftphpr(unit,simple,bitpix,naxis,naxes,0,1,extend,status)
  group=1
  fpixel=1
  call ftppre(unit,group,fpixel,npixels,image,status)
  call ftclos(unit, status)
  call ftfiou(unit, status)

  deallocate(image)
  deallocate(error)
end program dither

ওপিএস পোস্টে কুকুরছানা চিত্রের জন্য উদাহরণ আউটপুট:
কুকুরছানা এর বিচিত্র ছবি
ওপিএস উদাহরণ আউটপুট:
ওপিএস কুকুরছানা ছবি আঁকানো


এটি সত্যিই দুর্দান্ত দেখাচ্ছে, মানের জন্য অপরাজেয় হতে পারে
অদিতসু 4:16 '

ধন্যবাদ! আমি জানি না যে এটি অপরাজেয়, তবে এটি অন্যান্য ভাল অ্যালগরিদমের বিরুদ্ধে বিচার করা শক্ত (খুব সাবজেক্টিভ) হতে চলেছে।
আধা-বহিরাগত

1
আমি জানি আমি পিছনের সামঞ্জস্যকে গালাগাল করে কোডটি গল্ফ করি তবে বাস্তবে মনে হয় আপনি এটি স্ট্যান্ডার্ড হিসাবে অপব্যবহার করেছেন। এই কোডটি আসলে আমাকে কাঁদছে।
কাইল কানোজ 4'14

@ কাইলকানোস যখন আমার কোডটি কাউকে কাঁদে তখন আমি সর্বদা খুশি: p যদিও বিষয়টিতে এখানে বিশেষত ভয়াবহ? হ্যাঁ, আমি "অন্তর্নিহিত কোনওটিই" ব্যবহার করতে পারতাম না তবে এতে মজাটি কোথায়? আমি এটি কাজে মারাত্মক কোডিংয়ের জন্য ব্যবহার করি তবে গল্ফের জন্য নয়। এবং আমি স্পষ্টভাবে সম্মত হই যে সিএফআইটিএসআইও লাইব্রেরি এপিআই সম্পূর্ণরূপে ভয়াবহ (ftppre () একক সত্যিকারের নির্ভুলতার মধ্যে একটি FITS চিত্রকে আউটপুট দেয়, ftpprj () ডাবল পূর্ণসংখ্যার নির্ভুলতার মধ্যে একটি চিত্রকে আউটপুট দেয়) তবে এটি আপনার জন্য F77 পিছনের সামঞ্জস্যতা।
আধা-বহির্মুখী

1
ঠিক আছে, সুতরাং তাদের বেশিরভাগই কেবল আমার হয়ে ছিলেন op আমি এটি উন্নত। গঠনমূলক সমালোচনা সর্বদা প্রশংসা করা হয় :)
আধা-বহিরাগত

34

GraphicsMagick / করে ImageMagick

আদেশ দেওয়া:

magick B2DBy.jpg -gamma .45455 -ordered-dither [all] 4x4 ordered4x4g45.pbm

আমার "প্রতিষ্ঠিত অ্যালগরিদম" ব্যবহার করার বিষয়ে অভিযোগ করার আগে দয়া করে এপ্রিল 2003 এর গ্রাফিক্স ম্যাজিক এবং ইমেজম্যাগিকের জন্য চেঞ্জলগটি পড়ুন যেখানে আপনি দেখতে পাবেন যে আমি সেই অ্যাপ্লিকেশনগুলিতে অ্যালগরিদম প্রয়োগ করেছি। এছাড়াও, "-গম্মা .45455" "" -অর্ডারড-ডাইথেন "এর সংমিশ্রণটি নতুন।

"-Gamma .45455" চিত্রটি খুব হালকা হওয়ার যত্ন নেয়। "সমস্ত" পরামিতি কেবল গ্রাফিক্সম্যাগিকের সাথে প্রয়োজন।

সেখানে ব্যান্ডিং রয়েছে কারণ 4x4 অর্ডারযুক্ত-দুরে চিত্রটিতে কেবল 17 টি গ্রিলিভেল রয়েছে। X৫ টি স্তরযুক্ত একটি 8x8 আদেশযুক্ত-ব্যবহার করে ব্যান্ডিংয়ের উপস্থিতি হ্রাস করা যেতে পারে।

এখানে আসল চিত্র, 4x4 এবং 8x8 অর্ডার করা আঁকানো আউটপুট এবং এলোমেলো-প্রান্তিক আউটপুট: এখানে চিত্র বর্ণনা লিখুন

আমি অর্ডার-দিত সংস্করণটি পছন্দ করি তবে সম্পূর্ণতার জন্য এলোমেলো-প্রান্তিক সংস্করণটি অন্তর্ভুক্ত করছি।

magick B2DBy.jpg -gamma .6 -random-threshold 10x90% random-threshold.pbm

"10x90%" এর অর্থ হল 10 শতাংশ তীব্রতা পিক্সেলের নীচে খাঁটি কালো হিসাবে এবং 90 শতাংশের উপরে খাঁটি সাদা হিসাবে রেন্ডার করা, সেই অঞ্চলগুলিতে কয়েকটি একাকী ছোঁয়া এড়াতে।

এটি সম্ভবত লক্ষণীয় যে উভয়ই মেমরি-দক্ষ হিসাবে তারা সম্ভবত সম্ভব হতে পারে। উভয়ই কোনও বিচ্ছুরণ করে না, সুতরাং তারা অর্ডার-ডাইথ ব্লকগুলি লেখার সময়ও একবারে একটি পিক্সেল কাজ করে এবং প্রতিবেশী পিক্সেল সম্পর্কে কিছু জানার দরকার নেই। ইমেজম্যাগিক এবং গ্রাফিকস ম্যাগিক একবারে একটি সারিতে প্রক্রিয়া করে তবে এই পদ্ধতির জন্য এটি প্রয়োজনীয় নয়। অর্ডার-দুরের রূপান্তরগুলি আমার পুরানো x86_64 কম্পিউটারে .04 দ্বিতীয় আসল সময়ের চেয়ে কম সময় নেয়।


31
"আমার" প্রতিষ্ঠিত অ্যালগরিদম "ব্যবহারের বিষয়ে অভিযোগ করার আগে দয়া করে এপ্রিল 2003 এর গ্রাফিক্স ম্যাজিক এবং ইমেজম্যাগিকের জন্য চেঞ্জলগটি পড়ুন যেখানে আপনি দেখতে পাবেন যে আমি সেই অ্যাপ্লিকেশনগুলিতে অ্যালগরিদম প্রয়োগ করেছি।" নিখুঁত গালের জন্য +1।
জো জেড।

22

আমি কোড শৈলীর জন্য ক্ষমা চাইছি, আমি আমার জাভা ক্লাসে তৈরি কিছু লাইব্রেরি ব্যবহার করে এটি একত্রে ছুঁড়ে দিয়েছি এবং এতে অনুলিপি-পেস্ট এবং ম্যাজিক নম্বর রয়েছে case অ্যালগরিদম চিত্রটিতে এলোমেলো আয়তক্ষেত্রগুলি তুলে ধরে এবং খাঁজকাটি চিত্র বা মূল চিত্রটিতে গড় উজ্জ্বলতা বেশি কিনা তা পরীক্ষা করে। এরপরে এটি ব্রাইটনেসকে লাইনে আরও কাছে আনার জন্য একটি পিক্সেল চালু বা বন্ধ করে দেয়, পছন্দসইভাবে মূল চিত্র থেকে আরও পৃথক পিক্সেল বাছাই করে। আমি মনে করি এটি কুকুরছানাগুলির চুলের মতো পাতলা বিশদ আনার চেয়ে আরও ভাল কাজ করে তবে চিত্রটি উচ্চস্বরে, কারণ এটি এমন কোনও অঞ্চলেও বিশদ আনার চেষ্টা করে না।

এখানে চিত্র বর্ণনা লিখুন

public void dither(){
    int count = 0;
    ditheredFrame.suspendNotifications();
    while(count < 1000000){
        count ++;
        int widthw = 5+r.nextInt(5);
        int heightw = widthw;
        int minx = r.nextInt(width-widthw);
        int miny = r.nextInt(height-heightw);



            Frame targetCropped = targetFrame.crop(minx, miny, widthw, heightw);
            Frame ditherCropped = ditheredFrame.crop(minx, miny, widthw, heightw);

            if(targetCropped.getAverage().getBrightness() > ditherCropped.getAverage().getBrightness() ){
                int x = 0;
                int y = 0;
                double diff = 0;

                for(int i = 1; i < ditherCropped.getWidth()-1; i ++){
                    for(int j = 1; j < ditherCropped.getHeight()-1; j ++){
                        double d = targetCropped.getPixel(i,  j).getBrightness() - ditherCropped.getPixel(i, j).getBrightness();
                        d += .005* targetCropped.getPixel(i+1,  j).getBrightness() - .005*ditherCropped.getPixel(i+1, j).getBrightness();

                        d += .005* targetCropped.getPixel(i-1,  j).getBrightness() - .005*ditherCropped.getPixel(i-1, j).getBrightness();

                        d += .005* targetCropped.getPixel(i,  j+1).getBrightness() -.005* ditherCropped.getPixel(i, j+1).getBrightness();

                        d += .005* targetCropped.getPixel(i,  j-1).getBrightness() - .005*ditherCropped.getPixel(i, j-1).getBrightness();

                        if(d > diff){
                            diff = d;
                            x = i;
                            y = j;
                        }
                    }
                    ditherCropped.setPixel(x,  y,  WHITE);
                }

            } else {
                int x = 0;
                int y = 0;
                double diff = 0;

                for(int i = 1; i < ditherCropped.getWidth()-1; i ++){
                    for(int j = 1; j < ditherCropped.getHeight()-1; j ++){
                        double d =  ditherCropped.getPixel(i, j).getBrightness() -targetCropped.getPixel(i,  j).getBrightness();
                        d += -.005* targetCropped.getPixel(i+1,  j).getBrightness() +.005* ditherCropped.getPixel(i+1, j).getBrightness();

                        d += -.005* targetCropped.getPixel(i-1,  j).getBrightness() +.005* ditherCropped.getPixel(i+1, j).getBrightness();

                        d += -.005* targetCropped.getPixel(i,  j+1).getBrightness() + .005*ditherCropped.getPixel(i, j+1).getBrightness();

                        d += -.005* targetCropped.getPixel(i,  j-1).getBrightness() + .005*ditherCropped.getPixel(i, j-1).getBrightness();



                        if(d > diff){
                            diff = d;
                            x = i;
                            y = j;
                        }
                    }
                    ditherCropped.setPixel(x,  y,  BLACK);
                }
            }


    }
    ditheredFrame.resumeNotifications();
}

আমি নিলাম যে এটা নির্দোষ? যদি তাই হয়, এটি কত দ্রুত?
ousurous

এটি এলোমেলো, এবং আমার কম্পিউটারে প্রায় 3 সেকেন্ড সময় নেয়।
QuadmasterXLII

2
যদিও সবচেয়ে বড়-বিশ্বস্ততা অ্যালগরিদম না হলেও ফলাফলগুলি নিজেরাই শিল্প।
এজেম্যানসফিল্ড

4
আমি সত্যিই এই অ্যালগরিদমের চেহারা পছন্দ করি! তবে আমি মনে করি এটি আংশিকভাবে দেখতে বেশ ভাল দেখাচ্ছে কারণ এটি প্রায়শই পশুর তুলনায় একটি টেক্সচার তৈরি করে এবং এটি পশমযুক্ত একটি প্রাণী। তবে আমি নিশ্চিত যে এটি সত্য। আপনি একটি গাড়ি যেমন উদাহরণস্বরূপ অন্য ছবি পোস্ট করতে পারেন?
আধা-বহিরাগত

1
আমি মনে করি এটি অ্যালগরিদমের মৌলিকত্বের এবং ফলাফলের দুর্দান্ততার ক্ষেত্রে উভয়ই সেরা উত্তর। আমি এটি দেখতে চাই যে এটি অন্য কয়েকটি চিত্রের উপরও চালিত হয়।
নাথানিয়েল

13

ঘোস্টস্ক্রিপ্ট (ইমেজম্যাগিকের সামান্য সহায়তায়)

আমার 'নিজস্ব নতুন অ্যালগরিদম' হওয়া থেকে দূরে, তবে দুঃখিত, এটি প্রতিহত করতে পারেনি।

convert puppy.jpg puppy.pdf && \
convert puppy.jpg -depth 8 -colorspace Gray -resize 20x20! -negate gray:- | \
gs -q -sDEVICE=ps2write -o- -c \
    '<</Thresholds (%stdin) (r) file 400 string readstring pop 
       /HalftoneType 3 /Width 20 /Height 20
     >>sethalftone' \
    -f puppy.pdf | \
gs -q -sDEVICE=pngmono -o puppy.png -

এখানে চিত্র বর্ণনা লিখুন

অবশ্যই এটি 'একই আকারের' সংযম ছাড়াই আরও ভাল কাজ করে।


2
এটা হাস্যকর. এই ওয়ারহল ধাঁচের আশ্চর্য সম্পর্কে কেউ মন্তব্য করেননি বলে আমি হতবাক হয়েছি।
Andreï Kostyrka

10

জাভা

এখানে আমার জমা দেওয়া। একটি জেপিজি চিত্র গ্রহণ করে, প্রতি পিক্সেল আলোকিতত্বের জন্য পিক্সেল গণনা করে ( এই এসও প্রশ্নে বনানকে ধন্যবাদ ) এবং তারপরে ফলাফলটি পিক্সেলটি কালো বা সাদা হবে কিনা তা জানার জন্য এলোমেলো প্যাটার্নের বিপরীতে এটি পরীক্ষা করুন। ডার্কার্স্ট পিক্সেল সর্বদা কালো হবে এবং চিত্রের বিবরণ সংরক্ষণের জন্য উজ্জ্বলতম পিক্সেল সর্বদা সাদা হবে।

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;

public class DitherGrayscale {

    private BufferedImage original;
    private double[] threshold = { 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31,
            0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42,
            0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53,
            0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, 0.61, 0.62, 0.63, 0.64,
            0.65, 0.66, 0.67, 0.68, 0.69 };


    public static void main(String[] args) {
        DitherGrayscale d = new DitherGrayscale();
        d.readOriginal();
        d.dither();

    }

    private void readOriginal() {
        File f = new File("original.jpg");
        try {
            original = ImageIO.read(f);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void dither() {
        BufferedImage imRes = new BufferedImage(original.getWidth(),
                original.getHeight(), BufferedImage.TYPE_INT_RGB);
        Random rn = new Random();
        for (int i = 0; i < original.getWidth(); i++) {
            for (int j = 0; j < original.getHeight(); j++) {

                int color = original.getRGB(i, j);

                int red = (color >>> 16) & 0xFF;
                int green = (color >>> 8) & 0xFF;
                int blue = (color >>> 0) & 0xFF;

                double lum = (red * 0.21f + green * 0.71f + blue * 0.07f) / 255;

                if (lum <= threshold[rn.nextInt(threshold.length)]) {
                    imRes.setRGB(i, j, 0x000000);
                } else {
                    imRes.setRGB(i, j, 0xFFFFFF);
                }

            }
        }
        try {
            ImageIO.write(imRes, "PNG", new File("result.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

প্রক্রিয়াযুক্ত চিত্র

অন্যান্য উদাহরণ:

মূল প্রক্রিয়াকৃত

পুরো রঙের চিত্রগুলির সাথেও কাজ করে:

রঙিন চিত্র ফল


9

CJam

lNl_~:H;:W;Nl;1N[{[{ri}W*]{2/{:+}%}:P~}H*]z{P}%:A;H{W{I2/A=J2/=210/[0X9EF]=I2%2*J2%+m>2%N}fI}fJ

95 বাইট :)
এটি ইনপুট এবং আউটপুট উভয়ের জন্য কোনও মন্তব্য লাইন ছাড়াই ASCII PGM (P2) ফর্ম্যাট ব্যবহার করে।

পদ্ধতিটি খুব বেসিক: এটি 2 * 2 পিক্সেলের স্কোয়ার যুক্ত করে, 0..4 পরিসরে রূপান্তর করে, তারপরে 2 * 2 কালো-সাদা পিক্সেল উত্পন্ন করতে 4 বিটের সাথে সম্পর্কিত প্যাটার্ন ব্যবহার করে।
এর অর্থ হ'ল প্রস্থ এবং উচ্চতা সমান হওয়া উচিত।

নমুনা:

নির্দোষ কুকুরছানা

এবং মাত্র 27 বাইটে একটি এলোমেলোভাবে অ্যালগরিদম:

lNl_~*:X;Nl;1N{ri256mr>N}X*

এটি একই ফাইল ফর্ম্যাট ব্যবহার করে।

নমুনা:

এলোমেলো কুকুরছানা

এবং পরিশেষে একটি মিশ্র পদ্ধতির: একটি চেকারবোর্ড প্যাটার্নের দিকে পক্ষপাত সহ এলোমেলোভাবে ঝোঁক; 44 বাইট:

lNl_~:H;:W;Nl;1NH{W{ri128_mr\IJ+2%*+>N}fI}fJ

নমুনা:

মিশ্র কুকুরছানা


2
প্রথমটি নিন্টেন্ডো ডিএসির "ফ্লিপনোট স্টুডিও" অ্যাপ্লিকেশনটির সাথে তুলনীয়।
বব দ্য আশ্চর্যজনক

6

জাভা (1.4+)

আমি এখানে চাকাটি পুনরায় উদ্ভাবন করছি কিনা তা সম্পর্কে আমি নিশ্চিত নই তবে আমার ধারণা এটি অনন্য হতে পারে ...

সীমিত এলোমেলো ক্রম সহ

সীমিত এলোমেলো ক্রম সহ

খালি খালি এলোমেলো

খালি খালি এলোমেলো

এখানে চিত্র বর্ণনা লিখুন

অ্যাভারোয়েসের উত্তর থেকে শহর চিত্র

অ্যালগরিদম বৈশিষ্ট্য বজায় রাখতে স্থানীয় আলোকিত শক্তি এবং স্বাভাবিককরণের ধারণাটি ব্যবহার করে। প্রাথমিক সংস্করণটি পরে এলোমেলো ঝাঁকুনি ব্যবহার করে অনুরূপ আলোকসজ্জার ক্ষেত্রগুলিতে বিশিষ্ট চেহারা তৈরি করে। তবে এটি দৃশ্যত আবেদনযোগ্য ছিল না। এটির মোকাবিলা করতে, সীমিত র্যান্ডম সিকোয়েন্সগুলির একটি সীমিত সেট কাঁচা ইনপুট পিক্সেল লুমিনোসিটিতে ম্যাপ করা হয় এবং নমুনাগুলি পুনরাবৃত্তভাবে ব্যবহৃত হয় এবং বারবার খ্যাতিযুক্ত বর্ণন ব্যাকগ্রাউন্ড দেয়।

import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;

public class LocalisedEnergyDitherRepeatRandom {

    static private final float EIGHT_BIT_DIVISOR=1.0F/256;
    private static final int KERNEL_SIZE_DIV_2 =4;
    private static final double JITTER_MULTIPLIER=0.01;
    private static final double NO_VARIANCE_JITTER_MULTIPLIER=1.5;
    private static final int RANDOM_SEQUENCE_LENGTH=10;
    private static final int RANDOM_SEQUENCE_COUNT=20;
    private static final boolean USE_RANDOM_SEQUENCES=true;

    public static void main(String args[]) throws Exception
    {
        BufferedImage image = ImageIO.read(new File("data/dog.jpg"));
        final int width = image.getWidth();
        final int height = image.getHeight();
        float[][][] yuvImage =convertToYUVImage(image);
        float[][][] outputYUVImage = new float[width][height][3];
        double circularKernelLumaMean,sum,jitter,outputLuma,variance,inputLuma;
        int circularKernelPixelCount,y,x,kx,ky;
        double[][] randomSequences = new double[RANDOM_SEQUENCE_COUNT][RANDOM_SEQUENCE_LENGTH];
        int[] randomSequenceOffsets = new int[RANDOM_SEQUENCE_COUNT];

        // Generate random sequences
        for (y=0;y<RANDOM_SEQUENCE_COUNT;y++)
        {
            for (x=0;x<RANDOM_SEQUENCE_LENGTH;x++)
            {
                randomSequences[y][x]=Math.random();
            }
        }

        for (y=0;y<height;y++)
        {
            for (x=0;x<width;x++)
            {
                circularKernelLumaMean=0;
                sum=0;
                circularKernelPixelCount=0;

                /// calculate the mean of the localised surrounding pixels contained in 
                /// the area of a circle surrounding the pixel.
                for (ky=y-KERNEL_SIZE_DIV_2;ky<y+KERNEL_SIZE_DIV_2;ky++)
                {
                    if (ky>=0 && ky<height)
                    {
                        for (kx=x-KERNEL_SIZE_DIV_2;kx<x+KERNEL_SIZE_DIV_2;kx++)
                        {
                            if (kx>=0 && kx<width)
                            {
                                double distance= Math.sqrt((x-kx)*(x-kx)+(y-ky)*(y-ky));

                                if (distance<=KERNEL_SIZE_DIV_2)
                                {
                                    sum+=yuvImage[kx][ky][0];
                                    circularKernelPixelCount++;
                                }
                            }
                        }
                    }
                }

                circularKernelLumaMean=sum/circularKernelPixelCount;

                /// calculate the variance of the localised surrounding pixels contained in 
                /// the area of a circle surrounding the pixel.
                sum =0;

                for (ky=y-KERNEL_SIZE_DIV_2;ky<y+KERNEL_SIZE_DIV_2;ky++)
                {
                    if (ky>=0 && ky<height)
                    {
                        for (kx=x-KERNEL_SIZE_DIV_2;kx<x+KERNEL_SIZE_DIV_2;kx++)
                        {
                            if (kx>=0 && kx<width)
                            {
                                double distance= Math.sqrt((x-kx)*(x-kx)+(y-ky)*(y-ky));

                                if (distance<=KERNEL_SIZE_DIV_2)
                                {
                                    sum+=Math.abs(yuvImage[kx][ky][0]-circularKernelLumaMean);
                                }
                            }
                        }
                    }
                }

                variance = sum/(circularKernelPixelCount-1);

                if (variance==0)
                {
                    // apply some jitter to ensure there are no large blocks of single colour
                    inputLuma=yuvImage[x][y][0];
                    jitter = Math.random()*NO_VARIANCE_JITTER_MULTIPLIER;
                }
                else
                {
                    // normalise the pixel based on localised circular kernel
                    inputLuma = outputYUVImage[x][y][0]=(float) Math.min(1.0, Math.max(0,yuvImage[x][y][0]/(circularKernelLumaMean*2)));
                    jitter = Math.exp(variance)*JITTER_MULTIPLIER;
                }

                if (USE_RANDOM_SEQUENCES)
                {
                    int sequenceIndex =(int) (yuvImage[x][y][0]*RANDOM_SEQUENCE_COUNT);
                    int sequenceOffset = (randomSequenceOffsets[sequenceIndex]++)%RANDOM_SEQUENCE_LENGTH;
                    outputLuma=inputLuma+randomSequences[sequenceIndex][sequenceOffset]*jitter*2-jitter;
                }
                else
                {
                    outputLuma=inputLuma+Math.random()*jitter*2-jitter;
                }


                // convert 8bit luma to 2 bit luma
                outputYUVImage[x][y][0]=outputLuma<0.5?0:1.0f;
            }
        }

        renderYUV(image,outputYUVImage);
        ImageIO.write(image, "png", new File("data/dog.jpg.out.png"));
    }

      /**
       * Converts the given buffered image into a 3-dimensional array of YUV pixels
       * @param image the buffered image to convert
       * @return 3-dimensional array of YUV pixels
       */
      static private float[][][] convertToYUVImage(BufferedImage image)
      {
        final int width = image.getWidth();
        final int height = image.getHeight();
        float[][][] yuv = new float[width][height][3];
        for (int y=0;y<height;y++)
        {
          for (int x=0;x<width;x++)
          {
            int rgb = image.getRGB( x, y );
            yuv[x][y]=rgb2yuv(rgb);
          }
        }
        return yuv;
      }

      /**
       * Renders the given YUV image into the given buffered image.
       * @param image the buffered image to render to
       * @param pixels the YUV image to render.
       * @param dimension the
       */
      static private void renderYUV(BufferedImage image, float[][][] pixels)
      {
        final int height = image.getHeight();
        final int width = image.getWidth();
        int rgb;

        for (int y=0;y<height;y++)
        {
          for (int x=0;x<width;x++)
          {

            rgb = yuv2rgb( pixels[x][y] );
            image.setRGB( x, y,rgb );
          }
        }
      }

      /**
       * Converts a RGB pixel into a YUV pixel
       * @param rgb a pixel encoded as 24 bit RGB
       * @return array representing a pixel. Consisting of Y,U and V components
       */
      static float[] rgb2yuv(int rgb)
      {
        float red = EIGHT_BIT_DIVISOR*((rgb>>16)&0xFF);
        float green = EIGHT_BIT_DIVISOR*((rgb>>8)&0xFF);
        float blue = EIGHT_BIT_DIVISOR*(rgb&0xFF);

        float Y = 0.299F*red + 0.587F * green + 0.114F * blue;
        float U = (blue-Y)*0.565F;
        float V = (red-Y)*0.713F;

        return new float[]{Y,U,V};
      }

      /**
       * Converts a YUV pixel into a RGB pixel
       * @param yuv array representing a pixel. Consisting of Y,U and V components
       * @return a pixel encoded as 24 bit RGB
       */
      static int yuv2rgb(float[] yuv)
      {
        int red = (int) ((yuv[0]+1.403*yuv[2])*256);
        int green = (int) ((yuv[0]-0.344 *yuv[1]- 0.714*yuv[2])*256);
        int blue = (int) ((yuv[0]+1.77*yuv[1])*256);

        // clamp to 0-255 range
        red=red<0?0:red>255?255:red;
        green=green<0?0:green>255?255:green;
        blue=blue<0?0:blue>255?255:blue;

        return (red<<16) | (green<<8) | blue;
      }

}

3
খুব সুন্দর. এটি এখনও পর্যন্ত অন্য উত্তরগুলির চেয়ে আলাদাভাবে প্রভাব দেয়।
জিওবিটস

@ জিওবিটস হ্যাঁ, এটি কতটা কার্যকর তা আমাকে অবাক করে দিয়েছিল। তবে আমি নিশ্চিত নই যে এটি একে একে দূরে বলা হবে কারণ এটি একেবারে দৃশ্যমান ভিন্ন আউটপুট তৈরি করে
মোগি

এটি বেশ অনন্য দেখায়।
Qwr

5

পাইথন

ধারণাটি অনুসরণ করা হচ্ছে: চিত্রটি n x nটাইলগুলিতে বিভক্ত হয়ে গেছে । আমরা এই টাইলগুলির প্রত্যেকের গড় রঙ গণনা করি। তারপর আমরা রঙ পরিসীমা মানচিত্র 0 - 255পরিসরের 0 - n*nযা আমাদের একটি নতুন মান দেয় v। তারপরে আমরা সেই টাইল কালো থেকে সমস্ত পিক্সেল রঙ করি এবং এ vটাইল সাদা রঙের মধ্যে এলোমেলোভাবে রঙিন পিক্সেল। এটি অনুকূল থেকে অনেক দূরে তবে এখনও আমাদের স্বীকৃত ফলাফল দেয়। রেজোলিউশনের উপর নির্ভর করে, এটি সাধারণত n=2বা সেরা ক্ষেত্রে কাজ করে n=3। যদিও n=2আপনি ইতিমধ্যে 'কৃত্রিম রঙ গভীরতা থেকে শিল্পকর্ম খুঁজে পেতে পারেন, যদি n=3এটি ইতিমধ্যেই কিছুটা ঝাপসা পেতে পারেন। আমি ধরে নিয়েছি যে চিত্রগুলি একই আকারে থাকা উচিত, তবে আপনি অবশ্যই এই পদ্ধতিটি ব্যবহার করতে পারেন এবং আরও বিশদ পাওয়ার জন্য উত্পন্ন চিত্রটির আকারটি দ্বিগুণ / ট্রিপল করতে পারেন।

পিএস: আমি জানি যে আমি পার্টিতে কিছুটা দেরি করেছি, আমার মনে আছে যে চ্যালেঞ্জ শুরু হওয়ার পরে আমার কোনও ধারণা ছিল না তবে এখন এই মস্তিষ্কের তরঙ্গ ছিল =)

from PIL import Image
import random
im = Image.open("dog.jpg") #Can be many different formats.
new = im.copy()
pix = im.load()
newpix = new.load()
width,height=im.size
print([width,height])
print(pix[1,1])

window = 3 # input parameter 'n'

area = window*window
for i in range(width//window):     #loop over pixels
    for j in range(height//window):#loop over pixels
        avg = 0
        area_pix = []
        for k in range(window):
            for l in range(window):
                area_pix.append((k,l))#make a list of coordinates within the tile
                try:
                    avg += pix[window*i+k,window*j+l][0] 
                    newpix[window*i+k,window*j+l] = (0,0,0) #set everything to black
                except IndexError:
                    avg += 255/2 #just an arbitrary mean value (when were outside of the image)
                                # this is just a dirty trick for coping with images that have
                                # sides that are not multiples of window
        avg = avg/area
        # val = v is the number of pixels within the tile that will be turned white
        val = round(avg/255 * (area+0.99) - 0.5)#0.99 due to rounding errors
        assert val<=area,'something went wrong with the val'
        print(val)
        random.shuffle(area_pix) #randomize pixel coordinates
        for m in range(val):
            rel_coords = area_pix.pop()#find random pixel within tile and turn it white
            newpix[window*i+rel_coords[0],window*j+rel_coords[1]] = (255,255,255)

new.save('dog_dithered'+str(window)+'.jpg')

ফলাফল:

n=2:

এখানে চিত্র বর্ণনা লিখুন

n=3:

এখানে চিত্র বর্ণনা লিখুন


3

আপনার চাইলে যে কোনও ফাইল ফর্ম্যাট ভাল।

আসুন এই প্রশ্নের জন্য একটি খুব কমপ্যাক্ট, তাত্ত্বিক ফাইল ফর্ম্যাটটি সংজ্ঞায়িত করুন কারণ বিদ্যমান ফাইল ফরম্যাটের যে কোনও একটির জন্য দ্রুত উত্তর লিখতে খুব বেশি ওভারহেড রয়েছে।

চিত্র ফাইলের প্রথম চারটি বাইট যথাক্রমে পিক্সেলগুলিতে চিত্রের প্রস্থ এবং উচ্চতা নির্ধারণ করুন:

00000001 00101100 00000001 00101100
width: 300 px     height: 300 px

w * h0 থেকে 255 পর্যন্ত গ্রেস্কেল মানগুলির বাইটগুলি অনুসরণ করে :

10000101 10100101 10111110 11000110 ... [89,996 more bytes]

তারপরে, আমরা পাইথনে কোডের একটি অংশ (145 বাইট) সংজ্ঞায়িত করতে পারি যা এই চিত্রটি নেবে এবং করবে:

import random
f=open("a","rb");g=open("b","wb");g.write(f.read(4))
for i in f.read():g.write('\xff' if ord(i)>random.randint(0,255) else '\x00')

যে "dithers" সাদা বা কালো যে পিক্সেল গ্রেস্কেল মান সমান সম্ভাবনা সঙ্গে ফিরে।


নমুনা চিত্রটিতে প্রয়োগ করা হয়েছে, এটি এরকম কিছু দেয়:

কুকুর

এটি খুব সুন্দর নয়, তবে পূর্বরূপে ছোট আকারের হলে এটি দেখতে খুব সাদৃশ্যপূর্ণ বলে মনে হয় এবং পাইথনের মাত্র 145 বাইটের জন্য আমি মনে করি না আপনি আরও ভাল হতে পারেন।


আপনি একটি উদাহরণ ভাগ করতে পারেন? আমি বিশ্বাস করি এটি এলোমেলোভাবে ঘোরাঘুরি, এবং ফলাফলগুলি সবচেয়ে পরিষ্কার নয় ... সুন্দর প্রোফাইল চিত্র যদিও
Qwr

এটি প্রকৃতপক্ষে এলোমেলো, এবং আমি এই মুহূর্তে আপনার নমুনা ছবির একটি উদাহরণ তৈরি করছি।
জো জেড।

2
আমি মনে করি এটি একটি বিপরীতে উত্সাহ থেকে উপকৃত হতে পারে। আমি পাইথন জানি না, তবে আমি ধরেই নিয়েছি এলোমেলো র্যান্ডমিন্ট (0,255) 0 এবং 255 এর মধ্যে একটি এলোমেলো সংখ্যা বাছাই করছে 55 55 এবং 200 বলার মধ্যে সীমাবদ্ধ রাখার চেষ্টা করুন, যা এই পরিসরের বাইরের কোনও ছায়াকে খাঁটি কালো বা সাদা হতে বাধ্য করবে। অনেকগুলি ছবি সহ আপনি একটি ভাল, স্ট্রাইকিং ইমেজটি কোনও দমে যাওয়া ছাড়াই পেতে পারেন, কেবল একটি সাধারণ প্রান্তিকতা। (এলোমেলো + বৈপরীত্যের উত্সাহ আপনার বর্তমান চিত্র এবং সাধারণ প্রান্তিকের মধ্যে একটি চিত্রকে মধ্যবর্তী দেবে))
লেভেল রিভার সেন্ট

আমি মনে করি এলোমেলোভাবে ঘোরাফেরাকে জিগার ডাইনিং বলা উচিত (কারণ এটি জিজার কাউন্টারের আউটপুট বলে মনে হচ্ছে)। যারা একমত?
জো জেড।

1
ইমেজম্যাগিক এবং গ্রাফিকস ম্যাগিকটি "-random-threshold" বিকল্পের সাথে প্রায় বছর পূর্বে আমি "-ordered-dither" -র সাথে যোগ করেছি (আমার উত্তরে যুক্ত হয়েছে) এটি প্রায় অবিকল। আবার, গামার বাম্পিং সঠিক তীব্রতা পেতে সহায়তা করে। আমি "জিজার দিশেহারা" পরামর্শের সাথে একমত।
গ্লেন রেন্ডার্স-পেহারসন

3

গোক্ষুরা

একটি 24-বিট বা 32-বিট পিএনজি / বিএমপি ফাইল নেয় (জেপিজি এতে কিছু গ্রে দিয়ে আউটপুট উত্পাদন করে)। এটি রঙযুক্ত ফাইলগুলিতেও বর্ধমান ible

এটি চিত্রকে 3-বিট রঙে ছড়িয়ে দিতে গতি-অনুকূলকৃত ELA ব্যবহার করে, যা আপনার পরীক্ষার চিত্র দেওয়ার পরে কালো / সাদা হিসাবে ফিরে আসবে।

আমি কি উল্লেখ করেছি যে এটি সত্যিই দ্রুত?

use System.Drawing
use System.Drawing.Imaging
use System.Runtime.InteropServices
use System.IO

class BW_Dither

    var path as String = Directory.getCurrentDirectory to !
    var rng = Random()

    def main
        file as String = Console.readLine to !
        image as Bitmap = Bitmap(.path+"\\"+file)
        image = .dither(image)
        image.save(.path+"\\test\\image.png")

    def dither(image as Bitmap) as Bitmap

        output as Bitmap = Bitmap(image)

        layers as Bitmap[] = @[ Bitmap(image), Bitmap(image), Bitmap(image),
                                Bitmap(image), Bitmap(image), Bitmap(image),
                                Bitmap(image)]

        layers[0].rotateFlip(RotateFlipType.RotateNoneFlipX)
        layers[1].rotateFlip(RotateFlipType.RotateNoneFlipY)
        layers[2].rotateFlip(RotateFlipType.Rotate90FlipX)
        layers[3].rotateFlip(RotateFlipType.Rotate90FlipY)
        layers[4].rotateFlip(RotateFlipType.Rotate90FlipNone)
        layers[5].rotateFlip(RotateFlipType.Rotate180FlipNone)
        layers[6].rotateFlip(RotateFlipType.Rotate270FlipNone)

        for i in layers.length, layers[i] = .dither_ela(layers[i])

        layers[0].rotateFlip(RotateFlipType.RotateNoneFlipX)
        layers[1].rotateFlip(RotateFlipType.RotateNoneFlipY)
        layers[2].rotateFlip(RotateFlipType.Rotate270FlipY)
        layers[3].rotateFlip(RotateFlipType.Rotate270FlipX)
        layers[4].rotateFlip(RotateFlipType.Rotate270FlipNone)
        layers[5].rotateFlip(RotateFlipType.Rotate180FlipNone)
        layers[6].rotateFlip(RotateFlipType.Rotate90FlipNone)

        vals = List<of List<of uint8[]>>()
        data as List<of uint8[]> = .getData(output)
        for l in layers, vals.add(.getData(l))
        for i in data.count, for c in 3
            x as int = 0
            for n in vals.count, if vals[n][i][c] == 255, x += 1
            if x > 3.5, data[i][c] = 255 to uint8
            if x < 3.5, data[i][c] = 0 to uint8

        .setData(output, data)
        return output

    def dither_ela(image as Bitmap) as Bitmap

        error as decimal[] = @[0d, 0d, 0d]
        rectangle as Rectangle = Rectangle(0, 0, image.width, image.height)
        image_data as BitmapData = image.lockBits(rectangle, ImageLockMode.ReadWrite, image.pixelFormat) to !
        pointer as IntPtr = image_data.scan0
        bytes as uint8[] = uint8[](image_data.stride * image.height)
        pfs as int = Image.getPixelFormatSize(image.pixelFormat) // 8
        Marshal.copy(pointer, bytes, 0, image_data.stride * image.height)

        for y as int in image.height, for x as int in image.width
            position as int = (y * image_data.stride) + (x * pfs)
            for i in 3
                error[i] -= bytes[position + i]
                if Math.abs(error[i] + 255 - bytes[position + i]) < Math.abs(error[i] - bytes[position + i])
                    bytes[position + i] = 255 to uint8
                    error[i] += 255
                else, bytes[position + i] = 0 to uint8

        Marshal.copy(bytes, 0, pointer, image_data.stride * image.height)
        image.unlockBits(image_data)
        return image

    def getData(image as Bitmap) as List<of uint8[]>

        rectangle as Rectangle = Rectangle(0, 0, image.width, image.height)
        image_data as BitmapData = image.lockBits(rectangle, ImageLockMode.ReadOnly, image.pixelFormat) to !
        pointer as IntPtr = image_data.scan0
        bytes as uint8[] = uint8[](image_data.stride * image.height)
        pixels as List<of uint8[]> = List<of uint8[]>()
        for i in image.width * image.height, pixels.add(nil)
        pfs as int = Image.getPixelFormatSize(image.pixelFormat) // 8
        Marshal.copy(pointer, bytes, 0, image_data.stride * image.height)

        count as int = 0
        for y as int in image.height, for x as int in image.width
            position as int = (y * image_data.stride) + (x * pfs)
            if pfs == 4, alpha as uint8 = bytes[position + 3]
            else, alpha as uint8 = 255
            pixels[count] = @[
                                bytes[position + 2], #red
                                bytes[position + 1], #green
                                bytes[position],     #blue
                                alpha]               #alpha
            count += 1

        image.unlockBits(image_data)
        return pixels

    def setData(image as Bitmap, pixels as List<of uint8[]>)
        if pixels.count <> image.width * image.height, throw Exception()
        rectangle as Rectangle = Rectangle(0, 0, image.width, image.height)
        image_data as BitmapData = image.lockBits(rectangle, ImageLockMode.ReadWrite, image.pixelFormat) to !
        pointer as IntPtr = image_data.scan0
        bytes as uint8[] = uint8[](image_data.stride * image.height)
        pfs as int = Image.getPixelFormatSize(image.pixelFormat) // 8
        Marshal.copy(pointer, bytes, 0, image_data.stride * image.height)

        count as int = 0
        for y as int in image.height, for x as int in image.width
            position as int = (y * image_data.stride) + (x * pfs)
            if pfs == 4, bytes[position + 3] = pixels[count][3] #alpha
            bytes[position + 2] = pixels[count][0]              #red
            bytes[position + 1] = pixels[count][1]              #green
            bytes[position] = pixels[count][2]                  #blue
            count += 1

        Marshal.copy(bytes, 0, pointer, image_data.stride * image.height)
        image.unlockBits(image_data)

কুকুর

গাছ


পুনরাবৃত্তি হ্রাস করতে, আপনি কি একটি অস্থায়ী পরিবর্তনশীল তৈরি করা colএবং image.setPixel(x,y,col)খুব শেষ অবধি ছেড়ে যাওয়ার কথা বিবেচনা করেছেন ?
জোয়েটউইডেল

3
গাছের ছবিতে কী আছে?
জে ম্যানসফিল্ড

এটি দেখতে দুর্দান্ত লাগছে, এবং রঙগুলির সাথে কাজ করার একটি উদাহরণ দেয়।
ousurous

2

জাভা

নিম্ন স্তরের কোড, পিএনজিজে এবং একটি শব্দ সংযোজন প্লাস বেসিক বিস্তারণ ব্যবহার করে । এই প্রয়োগের জন্য গ্রেস্কেল 8-বিট পিএনজি উত্স প্রয়োজন।

import java.io.File;
import java.util.Random;

import ar.com.hjg.pngj.ImageInfo;
import ar.com.hjg.pngj.ImageLineInt;
import ar.com.hjg.pngj.PngReaderInt;
import ar.com.hjg.pngj.PngWriter;

public class Dither {

    private static void dither1(File file1, File file2) {
        PngReaderInt reader = new PngReaderInt(file1);
        ImageInfo info = reader.imgInfo;
        if( info.bitDepth != 8 && !info.greyscale ) throw new RuntimeException("only 8bits grayscale valid");
        PngWriter writer = new PngWriter(file2, reader.imgInfo);
        ImageLineInt line2 = new ImageLineInt(info);
        int[] y = line2.getScanline();
        int[] ye = new int[info.cols];
        int ex = 0;
        Random rand = new Random();
        while(reader.hasMoreRows()) {
            int[] x = reader.readRowInt().getScanline();
            for( int i = 0; i < info.cols; i++ ) {
                int t = x[i] + ex + ye[i];
                y[i] = t > rand.nextInt(256) ? 255 : 0;
                ex = (t - y[i]) / 2;
                ye[i] = ex / 2;
            }
            writer.writeRow(line2);
        }
        reader.end();
        writer.end();
    }

    public static void main(String[] args) {
        dither1(new File(args[0]), new File(args[1]));
        System.out.println("See output in " + args[1]);
    }

}

( যদি আপনি চেষ্টা করতে চান তবে এই জারটিকে আপনার বিল্ড পথে যোগ করুন)।

এখানে চিত্র বর্ণনা লিখুন

বোনাস হিসাবে: এটি মেমরির ব্যবহারে অত্যন্ত দক্ষ (এটি কেবল তিনটি সারি সংরক্ষণ করে) তাই এটি বিশাল চিত্রগুলির জন্য ব্যবহার করা যেতে পারে।


নিতপিক: আমি মনে করব "বিশাল চিত্রগুলির জন্য ব্যবহৃত" এতটা গুরুত্বপূর্ণ নয় (আপনি কি কখনও>> 8 জিবি গ্রেস্কেল পিএনজি দেখেছেন?) তবে "এম্বেড এম্বেডেড ডিভাইসে ব্যবহৃত" অনেক বেশি গুরুত্বপূর্ণ বিষয়।
আধা-বহিরাগত

আমি এটি পছন্দ করি তবে এটি প্রান্তগুলি, মিথথিংসের চারপাশে কিছুটা ঝাপসা দেখায়।
বব দ্য আশ্চর্যজনক

1

জাভা

রঙের চিত্রগুলি নিয়ে কাজ করার জন্য কেবল একটি সাধারণ আরএনজি ভিত্তিক অ্যালগরিদম, আরও কিছু যুক্তি। সম্ভাবনা আছেকোনও প্রদত্ত পিক্সেল সাদা রঙে সেট করার বি রয়েছে, অন্যথায় এটি কালোতে সেট করে; যেখানে সেই পিক্সেলের আসল উজ্জ্বলতা।

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.Scanner;

import javax.imageio.ImageIO;


public class Ditherizer {
    public static void main(String[]a) throws IOException{
        Scanner input=new Scanner(System.in);
        Random rand=new Random();
        BufferedImage img=ImageIO.read(new File(input.nextLine()));
        for(int x=0;x<img.getWidth();x++){
            for(int y=0;y<img.getHeight();y++){
                Color c=new Color(img.getRGB(x, y));
                int r=c.getRed(),g=c.getGreen(),b=c.getBlue();
                double bright=(r==g&&g==b)?r:Math.sqrt(0.299*r*r+0.587*g*g+0.114*b*b);
                img.setRGB(x,y,(rand.nextInt(256)>bright?Color.BLACK:Color.WHITE).getRGB());    
            }
        }
        ImageIO.write(img,"jpg",new File(input.nextLine()));
        input.close();
    }
}

কুকুরের চিত্রটির সম্ভাব্য ফলাফল এখানে:

এখানে চিত্র বর্ণনা লিখুন


আপনি নীচে যেখানে কেউ এটি পড়ছেন না তার পরিবর্তে আপনি কেন শীর্ষে ব্যাখ্যাটি যুক্ত করবেন না ? আমি সত্যিই সেই ধারণাটি পছন্দ করি =)
flawr
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.