CRA-W DMP Summer 2006

Erika Chin

Seattle, WA

My Homepage My Mentor My Journal My Final Project


My Journal

Over my ten weeks stay I will be keeping a weekly log of my progress, work, and thoughts.

Week 1
I arrived in Seattle on Saturday (June 3rd) this week. This gave me the weekend to unpack and get familiar with the area before starting work for the summer. Because UVA is on the semester system and UW is on the quarter system, our summer vacations don't match up very well. This means I've come to UW on what is probably the most hectic week of the year: Exam Week. This turned out to be both a good and bad thing. On the up side, I got to see what the normal atmosphere of the campus is like before everyone clears out for vacation. (OK, not exactly normal: I'm sure everyone is about 100 times more stressed out than they normally are, but nevertheless it still gave me a feel for the personality of the campus.) The down side of arriving during UW's quarter was that it was difficult finding an apartment. When looking for housing, I quickly realized that most summer subleases start after June 9th, the last day of UW's final exams - not exactly ideal when you are arriving one week before that. But everything worked out. I ended up subleasing from a UW girl that I had met a few months ago at Google's Anita Borg Scholarship Retreat. I've just moved into her place. Earlier this week, I stayed temporarily with a girl who lives in Steven's Court (one of UW's few on campus dorms) on the west side of campus. Although randomly found on Craig's List, the girl I'm staying with turned out to be very nice and her apartment was conveniently situated on campus (just a 10-minute, scenic walk to the EE building).

After getting settled into Li's place, on Sunday, I took the day to wander around UW and get acquainted with the area. The campus is very beautiful, and much to my surprise, the sun was out in all force without a cloud in the sky. And they say Seattle is rainy.... (Although everyone says that Seattle summers are great: sunny, but cool and not as rainy.) I discovered many hiking trails/bike paths. I also discovered what the UW students call "The Ave." which is the equivalent to UVA's "The Corner." It's a street with a ton of restaurants and college hangouts. It has many teriyaki, pho, bubble tea, Mediterranean, Indian, and Thai restaurants. Yummy!!! The one thing I still can't figure out is why it's called "The AVE" when the street itself is "University WAY."

On Monday, I went to the Electrical Engineering building, which is conveniently connected to the CS building. I met my mentor, Maya, the others in the lab, and Anjali Koppal, another girl here for the summer DMP program (Check out her site!). Everyone has been really nice and welcoming.

This week I did a lot of background reading on color and color management (what I will be working on over the summer). I read and edited research papers on color maps and dither techniques. I read a couple of textbooks on color, color spaces, color management, and different regression techniques. I also got acquainted with MatLab and LaTex, both of which I had never used before but will be using extensively over the summer. By the end of the week, I was creating code in MatLab to calculate the CIE94 delta E distance equation.

On the weekend: On Friday evening, I moved into my long-term summer sublet, located right behind University Village on the north side of campus (just 2 blocks off it). I also went to a lab mate's BBQ. His house is very close to Green Lake, which is a gorgeous 3-mile lake where many people take their dogs and run or bike around it. I must remember to go there another day. Maybe have a picnic. On Saturday, I went to downtown Seattle and wandered around Pike Place Market with Anjali and apartment mates. It's a fun area with rows and rows of vendors selling seafood (one of which tossed fish from one person to another), fruits, jams, and arts and crafts. I tasted my first Ranier cherries, yellow-pink cherries native to this area. They were delicious. I also recommend "Market Spice" tea. Ask me, if you want to know more about it.

On Sunday, they were holding Seattle's International Film Festival at Neptune Theatre on The Ave. and I saw Shinobi with Anjali and some of her Berkeley friends.


Week 2
This week I talked with Maya about my summer work. I will be working on inverse color management and specifically focusing on different types of adaptive neighborhoods, regression, and weighting techniques. Color management deals with the problem of sending a printer specific RGB colors and then observing that the colors are not what you expect. Inverse color management figures out what true RGB value must be sent into the printer in order to get the printer to print the color you want. Device-independent colors are measured in CIELab space. This means that a color in CIELab is not dependent on which device you use to produce the color. The product of inverse color management is a look up table (LUT) that takes a CIELab value and maps it to the RGB value that you must feed to the printer to get that color.

Given this problem, I then proceeded to research various parameters of the study:

I also started compiling and organizing relevant code from multiple sources.

On the weekend: I went to Fremont for the Fremont Fair. It's a yearly fair held on the second weekend in June. They had many small vendors and displays. They also had a parade at noon...and a very unique thing happened right before the parade. You may want to Google it... I had no idea that they had that.


Week 3
This week I finished researching various aspects of the design and then went over the preliminary design decisions with Maya. The 3-D look up table (LUT) will be 17*17*17 in CIELab space. A 1-D look up table will be included along with the 3-D LUT. When building the 3-D LUT to characterize the printer, the 1-D LUT will help calibrate (or linearize) the printer for greater accuracy. Here's an excerpt from a guide to create a 1-D look up table to calibrate a printer that I wrote this week:

"In the inverse color management problem, we want to know what RGB values must be sent to the printer in order to get the desired device-independent CIELab values. This is done in two main stages. The first stage is to calibrate (or linearize) the printer.

To do this, we first build three 1-D look up tables (LUTs) that will convert each channel, R, G, and B to R', G', and B' respectively (process to be described below). This will gray balance the printer so that equal amounts of R, G, and B (passed through the LUT) correspond approximately to neutral gray values. The R'G'B' will be the real values that produce the gray values in the printer.

The second stage is to characterize the printer. Using the calibrated RGB values and CIELab pairs, we create a 3-D LUT that will translate CIELab to RGB.

Once we have calibration and characterization functions for the printer, we can start with the desired CIELab values and pass the values through the characterization function (a 3-D LUT). From this we get the RGB. Then to calibrate the RGB values, we will pass each channel through the 1-D LUT to get R'G'B' values. The outcome is the R'G'B' value that when put into the printer, we will get out the expected RGB values."

The full (uneditted) pdf can be found here.

I also checked out the printers that I will be using in this experiment. They are the Epson Stylus 2200 and the HP Color Laser Jet 2550C. To prepare for the experiment, I changed the toner/ink cartridges and tested the ink quality. I also opened Photoshop, turned its own version of color management off (so that the settings won't affect the experiment), and printed out Chromix color test charts on each printer.

I also adjusted my compiled code to handle and build 1-D LUTs.

Questions to consider: Will the 1-D LUT need to be inverted to alter the RGB values in the training points before building the 3-D LUT?

On the weekend: I went to see the Pixar film, Cars, with Anjali and some Berkeley people. On Sunday, U-Village was having a sidewalk sale, so I did loads of shopping. Then later that evening, I went to dinner with family friends in Seattle. We went to this delicious tapas restaurant on Pike and Boren St. called Tango. It had the best dessert ever called "El Diablo." It was absolutely divine: chocolate with cayenne pepper, drizzled with tequila caramel, surrounded by burnt merengue, and topped with spicy almonds and cocoa nibs. Chocolate heaven. Mmmm.....


Week 4
This week I completed all the code that:

Process: For the experiment, I will be printing out the Chromix color chart of 918 patches. Then I will use a spectrophotometer to measure the CIELab value of each printed patch, one-by-one. The PNG of the Chromix chart will tell me what the RGB values of the patches are (the RGB values that were sent to the printer). The printed paper and results from the spectrophotometer will tell me what the printer actually printed. These (RGB, CIELab) pairs will become the training pairs. Then I will build a 17*17*17 table of test points that evenly span the CIELab space. These will be the test points. The program accepts as parameters, the type of neighborhood you would like it to evaluate and type of regression it should use. The types of neighborhoods are: (Neighborhoods to be explained in paper.) The program uses the training points to build the 1-D LUT (as described in last week's entry). Then using the inverse of the 1-D LUT, the RGB values of the training points are adjusted. The 3-D LUT is built by examining each test point, finding the training points (CIELab) that makes up its neighbors, and using their RBG values to estimate the RGB value of the test point via ridge or local linear regression. Now that both the 1-D and 3-D LUT are built, the program can take any input of CIELab value and return what the corresponding RGB value should be (to be sent to the printer). The CIELab value gets looked up in the 3-D LUT, and then the returned RGB values will be passed through the 1-D to get the R'G'B' values. To measure the error that these estimated LUTs yield, one just prints the R'G'B' patches of the CIELab values that were looked up and uses the spectrophotometer to measure the patches in CIELab. These values are then compared to the original CIELab values using the CIELab94 error method.

Other things of note: I also added another regression option that will let you do LIME (linear interpolation with maximum entropy) weighted regression. I picked out the paper that will be used for the tests, made sure the printers print without its preexisting color management, and now everything is ready for the preliminary neutral 1-D LUT tests (a pre-official experiment to run through what I will be doing for actual experiment. I'll just be measuring a smaller patch of shades of grays).

Questions to consider: How does one determine the points that will be used for error test points? Is it random (in RGB, then printed on the printer to get the CIELab)? Or should it be in even intervals (making sure the test points are off of the training points)? Decision: Just generate 730 random RGB values and 189 random values that approximately neutral (R, G, and B values are within 25 units of one another). The section of neutrals are important because the eye is more sensitive to changes in the neutral range.


Week 5
Happy July 4th!! This past weekend, my parents came to town (all the way from Washington D.C., yeah, the other Washington) and we drove up to Vancouver, B.C., Canada. One of the days we went to Victoria (the capital of B.C.) on Vancouver Island. For July 4th, back in the U.S., I went up one of the hills in Queen Anne and saw the fireworks from Kerry Park. It took us forever to find the street that Kerry Park was on, but eventually we did. (We didn't realize the street randomly stopped and started elsewhere, so we spent a long time driving up and down the street when we really wanted to be in a different section on a street of the same name.)

This week in the lab, work was very frustrating. Before I could do the neutral 1-D LUT tests, I created some simple test data with which to test my program. When I ran it, much to my horror, I got errors that were greater than 100. Clearly something was not right. I went back to incrementally testing all the functions, all of which seemed to work as expected when given simpler data. I found a few slight bugs and some boundary conditions that I had overlooked (Ex. Remembering to extrapolate if a value is outside of the known data points; otherwise NaN is returned. Accounting for the condition when only one neighbor is found; fixed by taking at least 4 neighbors). Yet I still got a large error. The problem was narrowed down to the fact that the resulting RGB values were returned from the program with the R and G columns reversed. I checked through the code and made sure I hadn't flip-flopped the columns anywhere. I hadn't. Finally, after many, many hours of frustration and confusion, I found it. It was not even one of my coding problems which was what made it so hard to find. It was a MatLab function. Apparently, when doing 3-D interpolation, there are two MatLab commands that are used in interp3. One is meshgrid and the other is ndmesh and the only difference between the two is that one returns the first two columns flip-flopped. :( The biggest debugging problem of the week.

On the weekend: I drove down to see Olympic National Park. I saw Hurricane Ridge and also the rain forest. The next day I went to see Snoqualmie Falls.


Week 6
To make some of the process less manual, I made scripts that would read the Chomix chart JPG to get the RGB values. I then realized that the JPG had altered the values of the colors when saving (JPG is lossy) so I had to find and save another Chromix chart. I made another script that would output a PNG of the resulting image that is created after the RGB values are looked up. This made it easier to see if the estimation worked while testing and it would also become the PNG that I used to print on the printer. I also learned how to use the spectrophotometer. Then I printed the neutral gray test patches and measured them. It took a surprisingly long time to measure all the patches. The spectrophotometer had different reading speed settings, short, medium, long, and manual. Long was too long of a wait and medium was too fast. So I had to read each patch manually. Then I ran the demo experiment. The LIME method went horribly wrong. I ran simulations to figure out how I would have to change the LIME constant for it to yield better results. I also experimented with the ridge regression constant.

I also started writing up the explanation and algorithms for the SEN and LIME problems.

Questions to consider: When should the values be clipped? Decision: Only at the end after passing the values through the 1-D LUTs. Clipping the values in the 1-D LUT is the same as effectively clipping after the 1-D LUT. Clipping between the 3-D and 1-D LUTs can actually negatively effect the values extrapolated on the boundary of the gamut. Clipping the 3-D LUT will creative an even greater error and cause a loss of information.

On the weekend: I went to Volunteer Park in the Capitol Hill area where they were holding Shakespeare in the Park. I saw "As You Like It."


Week 7
This week, I nailed down what I thought should be the ridge regression constant and delta for the LIME weights. Then I proceeded to do the final experiment on the HP LaserJet printer. Yay!!!! Unbeknownst to me, however, after I had already printed and measured both the training patch and the test patch, run the program, and created the PNGs for the results, as I started to print the resulting images on the printer, I found that the printer's imaging drum needed to be replaced. Oops. So I had to start the experiment over and use the Epson Stylus Photo 2200 printer. (Not a huge problem because we were going to test on that printer anyway, but it still had taken time to measure those other patches.) Once I measured the training and test patches for the Epson 2200, I then made one slight adjustment to the 1-D LUTs. Because the measured values were showing that the luminance only ranged from ~17-96 and not 0-100, the 1-D LUT could be made more accurate. I took the existing, measured range of luminance values and spread that over the 1-D LUT and not the whole 0-100 range. Then I sampled and estimated 255 levels within the new luminance range. This gives me a more finely sampled look up table whose estimates of the neutrals are closer to the actual neutrals. It gives more detail to the gray value estimations and reduces the chances of overextrapolations and crazy data. Then I ran the program and printed the 15 different pages of images that test the different neighborhoods and estimation techniques. 15 pages with each page having 918 patches. Oi...


Week 8

Measuring continued into the weekend...although I did take a break to go salsa dancing at Beso del Sol in Wallingford on Saturday night.

And 15*918 patches later....I finished! Upon looking at the results/errors, I found that the LIME method didn't actually improve the estimation. So I had to think some more on it. I started by playing with different values of delta, a constant that controlled how evenly balanced the LIME weights are. Some of my tests showed that possible images could be greatly tinted green. Because the results of varying deltas were so wild, Maya began to suspect that something was going wrong elsewhere. So we had to think so more on it. We finally discovered that the 1-D LUT was not monotonic, as assumed. This was due to natural noise that is introduced when measuring and estimating. Because we cannot assume the 1-D LUT is not monotonic, that creates a problem with finding the inverse of the table. Another problem is that the range of possible luminance does not range all of 0-100, so at the endpoints, the program tries to extrapolate a value, and since the endpoints may not be monotonic, the extrapolation can go wild. To fix this, we made sure that the program estimated the minimum existing value, instead of just extrapolating a value. This also introduced the problem of when to clip values. We decided that it would be best to clip between the 3-D and 1-D LUTs in order to reduce the possibilities of out-of-range estimates.

It involved more tweaking of code, clipping, and deriving the end points of the 1-D LUT a different way. Thus, with new code come new results...15 more pages of patches. But this time my wonderful mentor is sending the patches away to be measured professionally. Yay!!!!!! My poor hand is giving a grateful sigh of relief.

In order to make our tests as general as possible, we looked into other ways of estimation for non-linear data. A possibility would be to use generic ink in hopes that is not as calibrated for the Epson printer that uses Epson ink on Epson paper.

On the weekend: This weekend my sister came to town (also from Washington D.C.) On Saturday, we went to a Glass Workshop (and bought lovely glass earrings). Then we went to Pike Place Market, and at 4:30 we took a ferry to Blake Island. There we visited Tillicum Village (a Native American-esque village) and had dinner in a long house (yum!!! Salmon smoked on Alder wood and wild rice). While we were eating dinner we also saw a Native American Dance Performance. It was amazing. Then when we got back to downtown Seattle, we caught some of the Seafair Parade. On Sunday, we went to Fremont, and took a tour of Theo Chocolate Factory. Theo's is an organic, fair-trade certified chocolate factory. I found the process of making chocolate very interesting. And they made very unique types of chocolate: chai chocolate, vanilla chocolate, coconut curry chocolate, etc. We also saw the Fremont morning market.


Week 9
This week I printed and measured patches from the Epson Photo Stylus R300 using the generic ink. These patches were also sent to Chromix. Then I started my analysis of the errors, neighborhoods, and regression types. There doesn't seem to be a definite trend that one type of regression is better than the others. LIME finally seems to be an improvement on our methods. I started using LIME with other neighborhood types and not just 15 nearest neighbors. I also looked into the neighbor sizes of the neighborhoods and discovered some interesting things. Natural neighbors seemed to be gathering neighbors on the hundreds, but upon inspection, it turned out that if the test point is outside of the hull of the training points then the neighborhood is going to grab most of the point on the facet of the hull. But if the test point is inside the hull, then the neighborhood size will be something around 7 to 17.

As another test on natural neighbors, I looked at how the number of neighbors changes as the number of available points increase. As the number of points increase, the number of neighbors goes to ~15.

I also compared the results of the different methods as an image that maps the difference for each value and creates a color image that scales the color according to the difference in values. (imagesc)

I'm still trying to uncover why the LIME weights can be so close to one another and yet it is still yielding a noticable improvement.

The HP's imaging drum is still not here...


Week 10
For my last and final week, I did another printer experiment. Because the HP imaging drum still hadn't arrived, I decided to do the experiment on a different laser printer. After a hunt through the EE building, I chose a Ricoh Aficio 1232C Laser printer to run the experiment on. After I got the results, I analyzed the all the data from the three printer experiments and finished up my research. My results can be found by clicking on the link at the top of the page that says "My Final Project."

I had a great time at UW and it is definitely an experience that I would recommend to anyone thinking about attending graduate school. Thank you to my mentor, Maya Gupta, and the DMP for giving me this opportunity to do research. I learned a great deal about color management, research in general, and grad life.





Last updated: Aug 12, 2006