Czasami muszę napisać więcej dokumentacji niż tylko komentarze w kodzie. Czasami te wyjaśnienia wymagają zrzutów ekranu. Czasami warunki uzyskania takiego zrzutu ekranu są tak dziwne, że proszę dewelopera o zrobienie zrzutu ekranu. Czasami zrzut ekranu nie pasuje do moich specyfikacji i muszę zmienić jego rozmiar, aby ładnie wyglądał.
Jak widać, okoliczności, w których potrzebny jest magiczny „Lossless Screenshot Resizer”, są bardzo mało prawdopodobne. W każdym razie wydaje mi się, że potrzebuję go każdego dnia. Ale jeszcze nie istnieje.
Widziałem cię tutaj na PCG, która wcześniej rozwiązywała niesamowite łamigłówki graficzne , więc myślę, że ta jest dla ciebie nudna ...
Specyfikacja
- Program pobiera zrzut ekranu pojedynczego okna jako dane wejściowe
- Zrzut ekranu nie wykorzystuje efektów szklanych ani podobnych (więc nie musisz zajmować się żadnymi elementami, które prześwitują)
- Format pliku wejściowego to PNG (lub inny bezstratny format, dzięki czemu nie musisz zajmować się artefaktami kompresji)
- Format pliku wyjściowego jest taki sam jak format pliku wejściowego
- Program tworzy zrzut ekranu o innym rozmiarze jako wynik. Minimalne wymaganie zmniejsza się.
- Użytkownik określa oczekiwany rozmiar wyjściowy. Jeśli możesz podać wskazówki dotyczące minimalnego rozmiaru, jaki program może wyprodukować na podstawie podanych danych wejściowych, jest to pomocne.
- Zrzut ekranu wyjściowego nie może zawierać mniej informacji, jeśli jest interpretowany przez człowieka. Nie usuniesz treści tekstowych ani graficznych, ale usuniesz obszary tylko z tłem. Zobacz przykłady poniżej.
- Jeśli uzyskanie oczekiwanego rozmiaru nie jest możliwe, program powinien to zaznaczyć, a nie po prostu zawiesić lub usunąć informacje bez uprzedzenia.
- Jeśli program wskazuje obszary, które zostaną usunięte w celu weryfikacji, powinno to zwiększyć jego popularność.
- Program może wymagać innych danych wejściowych od użytkownika, np. W celu ustalenia punktu początkowego optymalizacji.
Zasady
To konkurs popularności. Odpowiedź z największą liczbą głosów w dniu 08.03.2015 zostaje zaakceptowana.
Przykłady
Zrzut ekranu systemu Windows XP. Rozmiar oryginału: 1003 x 685 pikseli.
Przykładowe obszary (czerwony: pionowy, żółty: poziomy), które można usunąć bez utraty jakichkolwiek informacji (tekstu lub obrazów). Zauważ, że czerwony pasek nie jest ciągły. Ten przykład nie wskazuje wszystkich możliwych pikseli, które można potencjalnie usunąć.
Bezstratnie zmieniono rozmiar: 783 x 424 pikseli.
Zrzut ekranu systemu Windows 10. Rozmiar oryginału: 999 x 593 pikseli.
Przykładowe obszary, które można usunąć.
Zrzut ekranu bezstratnie: 689 x 320 pikseli.
Zauważ, że jest ok, że tekst tytułu („Pobieranie”) i „Ten folder jest pusty” nie są już wyśrodkowane. Oczywiście byłoby lepiej, gdyby było wyśrodkowane, a jeśli twoje rozwiązanie to zapewnia, powinno stać się bardziej popularne.
źródło
Odpowiedzi:
Pyton
funkcja
delrows
usuwa wszystkie zduplikowane wiersze oprócz jednego i zwraca transponowany obraz, zastosowanie go dwa razy usuwa również kolumny i transponuje z powrotem. Dodatkowothreshold
kontroluje, ile pikseli może się różnić, aby dwie linie były nadal uważane za takie sameOdwrócenie komparatora
mask
od>
do<=
spowoduje wyświetlenie usuniętych obszarów, które są w większości pustymi miejscami.golfed (bo dlaczego nie)
Zamiast porównywać każdy piksel, patrzy tylko na sumę, jako efekt uboczny powoduje to również konwersję zrzutu ekranu do skali szarości i ma problemy z permutacjami zachowującymi sumę, jak strzałka w dół na pasku adresu Win8 zrzut ekranu
źródło
Java: spróbuj bezstratnie i wrócić do świadomej zawartości
(Najlepszy jak dotąd bezstratny wynik!)
Kiedy po raz pierwszy spojrzałem na to pytanie, pomyślałem, że to nie jest łamigłówka ani wyzwanie, tylko ktoś desperacko potrzebujący programu i jego kodu;) Ale leży w mojej naturze rozwiązywanie problemów ze wzrokiem, więc nie mogłem powstrzymać się od podjęcia tego wyzwania. !
Wymyśliłem następujące podejście i kombinację algorytmów.
W pseudokodzie wygląda to tak:
Zastosowane techniki:
Program
Program może przycinać zrzuty ekranu bezstratnie, ale ma opcję powrotu do przycinania uwzględniającego treść, która nie jest w 100% bezstratna. Argumenty programu można dostosować, aby uzyskać lepsze wyniki.
Uwaga: Program można ulepszyć na wiele sposobów (nie mam tyle wolnego czasu!)
Argumenty
Kod
Wyniki
Zrzut ekranu XP bezstratny bez pożądanego rozmiaru (Maksymalna kompresja bezstratna)
Argumenty: „image.png” 1 1 5 10 false 0
Wynik: 836 x 323
Zrzut ekranu XP do 800x600
Argumenty: „image.png” 800 600 6 10 prawda 60
Wynik: 800 x 600
Bezstratny algorytm usuwa około 155 linii poziomych, po czym algorytm wraca do usuwania treści, dzięki czemu można zobaczyć niektóre artefakty.
Zrzut ekranu systemu Windows 10 do 700x300
Argumenty: „image.png” 700 300 6 10 prawda 60
Wynik: 700 x 300
Algorytm bezstratny usuwa 270 linii poziomych, niż algorytm wraca do usuwania treści, które usuwa kolejne 29. W pionie używany jest tylko algorytm bezstratny.
Zrzut ekranu systemu Windows 10 z uwzględnieniem zawartości do 400 x 200 (test)
Argumenty: „image.png” 400 200 5 10 prawda 600
Wynik: 400 x 200
Był to test mający na celu sprawdzenie, jak będzie wyglądał obraz wynikowy po intensywnym użyciu funkcji rozpoznawania zawartości. Rezultat jest mocno uszkodzony, ale nie nierozpoznany.
źródło
C #, algorytm jakbym zrobił to ręcznie
To jest mój pierwszy program do przetwarzania obrazu i jego wdrożenie zajęło trochę czasu
LockBits
itp. Ale chciałem, żeby był szybki (używałParallel.For
), aby uzyskać niemal natychmiastową informację zwrotną.Zasadniczo mój algorytm opiera się na spostrzeżeniach dotyczących ręcznego usuwania pikseli ze zrzutu ekranu:
W tej chwili robię to tylko w poziomie. Wynik pionowy może wykorzystywać ten sam algorytm i działać na obrazie obróconym o 90 °, więc teoretycznie jest to możliwe.
Wyniki
Oto zrzut ekranu mojej aplikacji z wykrytymi regionami:
I to jest wynik dla zrzutu ekranu systemu Windows 10 i progu 48 pikseli. Wyjście ma szerokość 681 pikseli. Niestety nie jest doskonały (patrz „Wyszukaj pliki do pobrania” i niektóre pionowe słupki kolumn).
I jeszcze jeden z progiem 64 pikseli (szerokość 567 pikseli). To wygląda jeszcze lepiej.
Ogólny wynik zastosowania rotacji do kadrowania również ze wszystkich dna (567 x 304 pikseli).
W systemie Windows XP musiałem nieco zmienić kod, ponieważ piksele nie są dokładnie równe. Stosuję próg podobieństwa wynoszący 8 (różnica w wartości RGB). Zwróć uwagę na niektóre artefakty w kolumnach.
Kod
Cóż, moja pierwsza próba przetwarzania obrazu. Nie wygląda dobrze, prawda? Zawiera tylko główny algorytm, a nie interfejs użytkownika, a nie obrót o 90 °.
źródło
Haskell, używając naiwnego usuwania podwójnych linii sekwencyjnych
Niestety, ten moduł udostępnia jedynie funkcję z typem bardzo rodzajowe
Eq a => [[a]] -> [[a]]
, ponieważ nie mam pojęcia jak do edycji plików graficznych w Haskell, jednak jestem pewien, że to możliwe, aby tranform obrazu PNG do[[Color]]
wartości, a ja sobie wyobrazić,instance Eq Color
aby być łatwo definiowalne.Ta funkcja to
resizeL
.Kod:
Wyjaśnienie:
Uwaga:
a : b
oznacza elementa
poprzedzony listą typua
, w wyniku czego powstaje lista. To jest podstawowa konstrukcja list.[]
oznacza pustą listę.Uwaga:
a :: b
oznaczaa
rodzajb
. Na przykład jeślia :: k
,(a : []) :: [k]
gdzie,[x]
oznacza listę zawierającą elementy typux
.Oznacza to, że
(:)
sam, bez żadnych argumentów:: a -> [a] -> [a]
.->
Oznacza funkcję z czegoś do czegoś.Po
import Data.List
prostu dostaje trochę pracy, którą inni wykonali dla nas i pozwala nam korzystać z ich funkcji bez ich przepisywania.Najpierw zdefiniuj funkcję
nubSequential :: Eq a => [a] -> [a]
.Ta funkcja usuwa identyczne kolejne elementy listy.
Więc
nubSequential [1, 2, 2, 3] === [1, 2, 3]
. Teraz skrócimy tę funkcję jakonS
.Jeśli
nS
zostanie zastosowany do pustej listy, nic nie da się zrobić, a my po prostu zwracamy pustą listę.Jeśli
nS
zostanie zastosowany do listy z zawartością, wówczas można wykonać rzeczywiste przetwarzanie. W tym celu potrzebujemy drugiej funkcji, tutaj wwhere
klauzuli-, do użycia rekurencji, ponieważ naszanS
nie śledzi elementu do porównania.Nazywamy tę funkcję
g
. Działa poprzez porównanie pierwszego argumentu z nagłówkiem podanej mu listy i odrzucenie głowy, jeśli się zgadzają, i wywołanie samego ogona ze starym pierwszym argumentem. Jeśli nie, dołącza głowę do ogona, przechodzi przez nią z głową jako nowy pierwszy argument.Aby go użyć
g
, podajemy go jako argument argumentunS
i ogon jako dwa argumenty.nS
jest teraz typuEq a => [a] -> [a]
, bierze listę i zwraca listę. Wymaga to, abyśmy mogli sprawdzić równość między elementami, tak jak dzieje się to w definicji funkcji.Następnie komponujemy funkcje
nS
itranspose
posługujemy się(.)
operatorem.Komponowanie funkcje oznaczają:
(f . g) x = f (g (x))
.W naszym przykładzie
transpose
obraca tabelę o 90 °,nS
usuwa wszystkie kolejne równe elementy listy, w tym przypadku inne listy (taka właśnie jest tabela),transpose
obraca ją z powrotem inS
ponownie usuwa kolejne równe elementy. To zasadniczo usuwa kolejne zduplikowane wiersze i kolumny.Jest to możliwe, ponieważ jeśli
a
można sprawdzić równość (instance Eq a
),[a]
to również.W skrócie:
instance Eq a => Eq [a]
źródło